16
votes

I'm using AUCTeX and I would like to bind a key, e.g. C-0, that does the following:

  1. Saves the active file without prompting me.
  2. Runs latexmk on the active file without prompting me.
  3. Shows me errors if latexmk encounters any by .

My problem is not how to bind a key (for which Tyler posted a link in a comment below) but how to come up with a function that accomplishes item 1–3.


I call Latexmk by

(add-hook 'LaTeX-mode-hook (lambda ()
  (push 
    '("Latexmk" "latexmk %s" TeX-run-TeX nil t
      :help "Run Latexmk on file")
    TeX-command-list)))

This is my .latexmkrc

$pdf_mode = 1;
$recorder = 1;
$latex = 'latex -recorder -halt-on-error -interaction=nonstopmode -shell-escape';
$pdflatex = 'pdflatex -recorder -halt-on-error -interaction=nonstopmode -shell-escape';

I'm using Emacs 23.3 and AUCTeX 11.86.

3
What you're asking for is very close to functions that are already available in the default AucTex package. You might start with this question: stackoverflow.com/questions/2199678/… which will get latexmk sorted for you, then work on tweaking that, if necessary, to get the particular behavior you want.Tyler
@Tyler Thanks. How can I bind such a command to a key?N.N.
If you follow the first answer, C-c C-c should compile your tex file with latexmk (you may have to alter the config files to get latexmk to popup as your default, but AucTex usually knows what to do). The actual command that's run is TeX-command-master, which you can bind using the usual approach: masteringemacs.org/articles/2011/02/08/…Tyler
@Tyler C-c C-c still prompts me even if it's the default.N.N.
There's a follow up to this question at stackoverflow.com/questions/7885853/…N.N.

3 Answers

14
votes

Something like this?

(require 'tex-buf)

(defun run-latexmk ()
  (interactive)
  (let ((TeX-save-query nil)
        (TeX-process-asynchronous nil)
        (master-file (TeX-master-file)))
    (TeX-save-document "")
    (TeX-run-TeX "latexmk" "latexmk" master-file)
    (if (plist-get TeX-error-report-switches (intern master-file))
        (TeX-next-error t)
      (minibuffer-message "latexmk done"))))

(add-hook 'LaTeX-mode-hook
          (lambda () (local-set-key (kbd "C-0") #'run-latexmk)))

Edit: TeX-save-document saves your master file and any sub-files (if you just have one file, it's your master file), and when TeX-save-query is nil, it doesn't ask you for confirmation. Then TeX-run-TeX runs latexmk using the mechanism usually used for running TeX, which includes error message parsing, but because it usually starts an asynchronous process, we set TeX-process-asynchronous to nil to wait for it to end. The odd-looking plist-get form is the documented way to check for errors from TeX-run-TeX (see comments in tex-buf.el), and if there are errors, we jump to the first one; if there are no errors, we show a message in the minibuffer just for fun.

Finally, the local-set-key is one way to bind a key to the function.

3
votes

Does this do what you want?

(defun my-tex ()
"Saves the current buffer and runs LaTeX, all with no prompts or further interaction."
  (interactive)
  (save-buffer)
  (TeX-command "LaTeX" 'TeX-master-file -1))

I don't use latexmk, but to make that work all you need to do is switch the string "LaTeX" for the name string you use for latexmk in TeX-command-list (which is probably just "latexmk" or "Latexmk").

I'm glad you asked, as this will be useful for me now!

2
votes

Assuming you've already used the answer in How to call latexmk in emacs, and jump to next-error to add latexmk to the command list for AUCTeX, you can use the following function:

(defun run-latexmk ()
  (interactive)
  (save-buffer)
  (TeX-command "Latexmk" 'TeX-master-file 0)
  (if (plist-get TeX-error-report-switches (intern (TeX-master-file)))
      (next-error))) ;; 0 -> suppress confirmation

And use any of the key-binding techniques to bind it to C-0; here's one that's local to the TeX mode:

(define-key TeX-mode-map (kbd "C-0") 'run-latexmk)

The run-latexmk function is based on digging through TeX-command-master, and simplifying it to your needs. Note that the call to (next-error) may not always happen, because LaTeX may get confused by your error and pause waiting for input