How do I bind latexmk to one key in Emacs and have it show errors if there are any
Asked Answered
S

4

17

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.

Steib answered 28/9, 2011 at 17:40 Comment(5)
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: #2200178 which will get latexmk sorted for you, then work on tweaking that, if necessary, to get the particular behavior you want.Pazpaza
@Pazpaza Thanks. How can I bind such a command to a key?Steib
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/…Pazpaza
@Pazpaza C-c C-c still prompts me even if it's the default.Steib
There's a follow up to this question at #7886353Steib
S
15

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.

Stockwell answered 18/10, 2011 at 17:24 Comment(7)
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...Leonidaleonidas
Oh I see, you set TeX-process-asynchronous to nil, so that simply doesn't happen... Well, that ought to work :-)Leonidaleonidas
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".Steib
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).Steib
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?Steib
I got help fixing the problem in #7886353. Could you please explain what (require 'tex-buf) is for? None of the other solution has that line.Steib
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?Sherwood
P
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!

Pazpaza answered 18/10, 2011 at 14:49 Comment(2)
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.Steib
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.Pazpaza
L
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

Leonidaleonidas answered 18/10, 2011 at 14:50 Comment(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.Steib
I also get "TeX-command-expand: Wrong type argument: stringp, nil" when I try to run-latexmk.Steib
@Steib 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?Leonidaleonidas
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.Steib
K
0

I use a custom minor mode that runs latexmk in the background and reports any errors/warnings via flymake. Their number is displayed in the mode line, and you can navigate them using (e.g.) M-n and M-p. In particular, the three steps you describe happen every time you save the file.

I use this only for single-file projects; it may not cover your use cases.

Kiaochow answered 7/2 at 16:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.