I currently use emacs for making and editing LaTeX documents. When compiling, I use an external program to compile into pdf. Right now, with the following code in my
.emacs file, emacs will start compiling the document into a pdf whenever I save the file.
(defun auto-compile-latex () (save-window-excursion (async-shell-command (format "cd %s; scons -u" default-directory)))) (add-hook 'LaTeX-mode-hook '(lambda () (add-hook 'after-save-hook 'auto-compile-latex nil 'make-it-local)))
I prefer this over
M-x compile, because I am more in the habit of saving, and it launches in the background, allowing me to continue working. However, I do not get a prominent notification when the compilation process finishes.
Ideally, I would want to run the following function whenever a compilation process finishes.
(defun latex-compilation-status (exit-code) (if (/= exit-code 0) (setq mode-name (propertize mode-name 'face 'font-lock-warning-face)) (setq mode-name (propertize mode-name 'face 'mode-line-highlight))))
That way, I can have the color in the mode line automatically change depending on whether the compilation was successful or not. However, looking through the emacs documentation, I have not found any mention of a hook that gets run after
async-shell-command completes. I know that there is the message in the minibuffer stating the exit status of the subprocess, but if I am typing at the time, it is often hard to notice.
Alternatively, I could wait for the shell command to complete, then change the color immediately. However, this then makes the entirety of emacs freeze while compiling, which is not desired.
How would I go about having this indication applied at the end of the compilation, without having emacs freeze during the process?
Here is another option using
set-process-sentinel based upon a prior helpful answer by
Francesco. Please do be careful, however, about using a
let binding to define a
start-process (which [in my lay opinion] is a definite "no no") because that would cause the process to begin immediately before its time. [FYI:
Nicolas has gotten me out of quite a few jams in the past, so please be sure to take a good hard look at his solution also.]
Emacs: if latexmk finishes okay, then show pdf, else display errors
You would just add your function to the last part of the function dealing with success -- i.e.,
(when (= 0 (process-exit-status p)) . . .:
(defun latexmk () ".latexmkrc contains the following entries (WITHOUT the four backslashes): $pdflatex = 'pdflatex -file-line-error -synctex=1 %O %S && (cp \"%D\" \"%R.pdf\")'; $pdf_mode = 1; $out_dir = '/tmp';" (interactive) (setq tex-file buffer-file-name) (setq pdf-file (concat "/tmp/" (car (split-string (file-name-nondirectory buffer-file-name) "\\.")) ".pdf")) (setq line (format "%d" (line-number-at-pos))) (setq skim "/Applications/Skim.app/Contents/SharedSupport/displayline") (setq tex-output (concat "*" (file-name-nondirectory buffer-file-name) "*") ) (setq latexmk "/usr/local/texlive/2012/texmf-dist/scripts/latexmk/latexmk.pl") (setq latexmkrc "/Users/HOME/.0.data/.0.emacs/.latexmkrc") (if (buffer-modified-p) (save-buffer)) (delete-other-windows) (set-window-buffer (split-window-horizontally) (get-buffer-create tex-output)) (with-current-buffer tex-output (erase-buffer)) (set-process-sentinel (start-process "compile" tex-output latexmk "-r" latexmkrc tex-file) (lambda (p e) (when (= 0 (process-exit-status p)) (start-process "displayline" nil skim "-b" line pdf-file tex-file) (switch-to-buffer (get-file-buffer tex-file)) (if (get-buffer-process (get-buffer tex-output)) (process-kill-without-query (get-buffer-process (get-buffer tex-output)))) (kill-buffer tex-output) (delete-other-windows)))))