Emacs: if latexmk finishes okay, then show pdf, el

2020-02-13 04:09发布

Could anyone please give me hand with the step between the first start-process and the second start-process. The second start-process that displays the pdf-file should run only if the first start-process finishes without errors. There is probably some type of successful exit code that can be spotted, but I would need some help please in that regard.

I'm open to suggestions regarding how best to determine whether the first start-process finished without errors. One method would be to look at the output buffer to determine whether the last line is equal to "Process process finished". Making the *.pdf file can take a few seconds even if it is without errors, and the second start-process fails if it begins too early. Sit-for is not the best option, since the second start-process should be aborted if the first start-process did not complete correctly. Generating the output buffer also takes a couple of seconds, so checking the last line in the buffer would also need to wait until the first start-process finishes. However, spotting a successful exit code (if such a thing exists) would be better than searching an output buffer for a string equals . . . .

FYI: The .latexmkrc $pdflatex line of code puts a copy of the *.pdf back into the working directory, and the .latexmkrc $out_dir line of code puts all of the auxiliary files into the /tmp folder. This is needed because Tex-Live for OSX does not support $aux_dir. The result is a clean working directory containing just *.tex and *.pdf files.

(defun latexmk ()
  ".latexmkrc should contain the following entries -- without the backslashes:
  $pdflatex .= ' && (cp \"%D\" \"%R.pdf\")';
  $force_mode = 1;
  $pdf_mode = 1;
  $out_dir = '/tmp';"
(interactive)
  (let* (
    (process (file-name-nondirectory buffer-file-name))
    (output (concat "*" (file-name-nondirectory buffer-file-name) "*") )
    (latexmk "/usr/local/texlive/2012/texmf-dist/scripts/latexmk/latexmk.pl")
    (arg-1 "-interaction=nonstopmode")
    (arg-2 "-file-line-error")
    (arg-3 "-synctex=1")
    (arg-4 "-r")
    (arg-5 "/Users/HOME/.0.data/.0.emacs/.latexmkrc")
    (pdf-file (concat "/tmp/" (car (split-string
      (file-name-nondirectory buffer-file-name) "\\.")) ".pdf"))
    (line (format "%d" (line-number-at-pos)))
    (skim "/Applications/Skim.app/Contents/SharedSupport/displayline") )
  (if (buffer-modified-p)
    (save-buffer))
  (start-process process output latexmk arg-1 arg-2 arg-3 arg-4 arg-5 buffer-file-name)
  ;;  (if (last line of output buffer is "Process 'process' finished")
      (start-process "displayline" nil skim "-b" line pdf-file buffer-file-name)
    (switch-to-buffer output)
  ;;  )
    ))

EDIT: A working solution based upon the concept outlined by Francesco in the answer below is available in a related thread: https://tex.stackexchange.com/a/156617/26911

标签: emacs elisp
1条回答
一纸荒年 Trace。
2楼-- · 2020-02-13 04:54

This answer provides a way to chain asynchronous commands, using sentinels to wait for each command to terminate before running the following.

You need to adapt the sentinel in order to check the process exit status using process-exit-status. A minimal working example for you should be along the lines of:

(defun run-latexmk ()
  "Asynchronously run `latexmk' and attach a sentinel to it"
  (let ((process (start-process "latexmk" "*output*"
                                "/bin/sh" "-c" "echo KO; false")))
    (set-process-sentinel process 'latexmk-sentinel)))

(defun latexmk-sentinel (p e)
  "Display the pdf if `latexmk' was successful"
  (when (= 0 (process-exit-status p))
    (start-process "displaypdf" "*output*"
                   "/bin/echo" "DISPLAY PDF")))

;; Example use
(with-current-buffer (get-buffer-create "*output*") (erase-buffer))
(run-latexmk)
查看更多
登录 后发表回答