16

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.

N.N.
  • 8,336
  • 12
  • 54
  • 94
  • 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: http://stackoverflow.com/questions/2199678/how-to-call-latexmk-in-emacs-and-jump-to-next-error which will get latexmk sorted for you, then work on tweaking that, if necessary, to get the particular behavior you want. – Tyler Sep 28 '11 at 20:08
  • @Tyler Thanks. How can I bind such a command to a key? – N.N. Sep 28 '11 at 20:44
  • 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: http://www.masteringemacs.org/articles/2011/02/08/mastering-key-bindings-emacs/ – Tyler Sep 28 '11 at 21:23
  • @Tyler `C-c C-c` still prompts me even if it's the default. – N.N. Oct 18 '11 at 07:16
  • There's a follow up to this question at http://stackoverflow.com/questions/7885853/emacs-latexmk-function-throws-me-into-an-empty-buffer-and-increases-the-height-o – N.N. Oct 25 '11 at 07:18

3 Answers3

14

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.

Jouni K. Seppänen
  • 43,139
  • 5
  • 71
  • 100
  • That's pretty close to what I've been tweaking with. But on my system at least (a windows box), LaTeX is run asynchronously, and so the `(plist-get ...)` doesn't reliably return true. I managed to work around it by advising `TeX-TeX-sentinel-check`, but that seems incredibly hackish... – Ben Lerner Oct 18 '11 at 18:35
  • Oh I see, you set TeX-process-asynchronous to nil, so that simply doesn't happen... Well, that ought to work :-) – Ben Lerner Oct 18 '11 at 18:50
  • 2
    Your code seems to do what I want in most cases. However, when I'm editing a large file and do `C-0` and there's an error and it popups as expected but the top buffer is changed to a buffer named "TeX Live 2011". – N.N. Oct 19 '11 at 09:23
  • I think the problem is triggered by a combination of pdflatex's shell escape and `\include`. Here's a test case that produces the problem `\immediate\write18{sh ./vc}\input{vc}\documentclass{article}\begin{document}text\end{document}` (removed the line breaks to fit in a comment). – N.N. Oct 19 '11 at 18:39
  • Also, now the minibuffer slightly expands in height as `run-latexmk` is run and then pops back to normal height after it's done. Is it possible to make it so that the minibuffer's height is not changed? – N.N. Oct 20 '11 at 13:22
  • I got help fixing the problem in http://stackoverflow.com/questions/7885853/emacs-latexmk-function-throws-me-into-an-empty-buffer. Could you please explain what `(require 'tex-buf)` is for? None of the other solution has that line. – N.N. Nov 09 '11 at 20:34
  • Nice snippet, how can I make the run-latexmk command which is bound to C-0 to accept a prefix such as C-u to prompt the command line so I can change part of the prompt such as the latexmk option or master-file name? – CodyChan Sep 14 '16 at 02:19
3

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!

N.N.
  • 8,336
  • 12
  • 54
  • 94
Tyler
  • 9,872
  • 2
  • 33
  • 57
  • 1
    I does satisfies item 1 and 2 of my list. I'd like a window showing errors if there are any. I'm using `-interaction=nonstopmode` with pdflatex so I'd only like to see the error that it stops with. – N.N. Oct 18 '11 at 15:18
  • Sorry, I don't know how latexmk works so I'm not sure where to go. You have inspired me to investigate getting Auctex to fill in for latexmk though - it should be possible to get Auctex to figure out how many times to run pdflatex and bibtex without having to keep hitting C-c C-c. That's going to take a bit more poking around though. – Tyler Oct 18 '11 at 17:09
2

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

Community
  • 1
  • 1
Ben Lerner
  • 184
  • 4
  • I get "Symbol's value as variable is void: TeX-mode-map" when I try the keybinding even if I wrap it in `eval-after-load 'tex`. – N.N. Oct 18 '11 at 15:11
  • 1
    I also get "TeX-command-expand: Wrong type argument: stringp, nil" when I try to run-latexmk. – N.N. Oct 18 '11 at 15:17
  • @N.N. I admit I didn't actually run it from the key binding, but just `M-x run-latexmk`, and that worked for me... Trying it now, though, I don't see the errors you do. You can fix the "Symbol's value..." error by wrapping the `define-key` with `(add-hook 'LaTeX-mode-hook (lambda () (define-key...))`, which ensures you're in LaTeX mode. I can reproduce the TeX-command-expand error, but only if I call it directly, which the code above does not... Does using the mode hook fix both problems, or just one problem for you? – Ben Lerner Oct 18 '11 at 15:42
  • Mode hook fixes the keybinding but run-latexmk still returns "Wrong type argument: stringp, nil". I've updated my question with information about my setup if that matters. – N.N. Oct 18 '11 at 15:47