Specifically, I want the binding 'C-x C-a' to do 'C-x C-s' then 'C-c C-a'. (Context: I'd like to save my TeX document, then have AUCTeX render it.) How can I do this? I don't want to map 'C-x C-a' to any specific command, or to re-bind it to exactly one other thing, which is what most of the Google results turn up.
2 Answers
For this special case (save a *TeX buffer before running the compiler), you don't need to define a binding, or advice a function, but just set TeX-save-query
to nil:
(setq TeX-save-query nil)
The general way to link multiple key-bindings to a single binding is a Keyboard Macro ((emacs) Keyboard Macros).
Keyboard macros can either be 'recorded' interactively, or written in elisp (in string or vector format). The easiest way to produce the latter is to use the kbd
function, so that you can write the keystrokes using the familiar syntax Emacs uses to display them (i.e. the same as you see when using C-h c
or C-h k
to ask about a key sequence).
@youngfrog has provided an example of this approach:
(define-key LaTeX-mode-map (kbd "C-x C-a") (kbd "C-x C-s C-c C-a"))
In this form, the first kbd
describes the key sequence to bind the command to, and the second kbd
provides the keyboard macro command that will be called.
As @Giordano points out, you need to make sure this form gets run after AucTex is loaded. You can do this by adding it to your LaTeX-mode-hook
:
(add-hook 'LaTeX-mode-hook 'my-latex-mode-hook)
(defun my-latex-mode-hook ()
(define-key LaTeX-mode-map
(kbd "C-x C-a")
(kbd "C-x C-s C-c C-a"))
;; and other customizations here...
)
You could also wrap the define-key
form in (eval-after-load "latex" '(define-key ...))
Interactively defining keyboard macros
Keyboard macros are commonly defined ('recorded') interactively. This is often more convenient (especially for cases where no long-term keybinding is required, but you can still do that if you wish to).
To record a keyboard macro:
- Press
<f3>
- Enter your commands (i.e.,
C-x C-s
C-x C-a
) [maybe you actually wantM-x TeX-save-document
here instead ofC-x C-s
?] - Press
<f4>
You can then repeat this command by pressing <f4>
.
If you want to save this macro for future use, first give it a name:
- enter
C-x C-k n
, and enter a name, eg. "my-tex-run"
You can then insert the macro code in your .emacs
file:
M-x insert-kbd-macro
, and enter the name of the macro
Now you have the code necessary to rebuild your macro:
(fset 'my-tex-run
(lambda (&optional arg) "Keyboard macro." (interactive "p")
(kmacro-exec-ring-item (quote ("" 0 "%d")) arg)))
You can then use this function in a keybinding command:
(define-key LaTeX-mode-map (kbd "C-x C-a") 'my-tex-run)
This works fine for putting together quick combinations of commands. However, if you can use customization variables (like the answer @Giordano gave), or use actual elisp code, it will be easier to modify your macro if you want to tweak it beyond just duplicating the raw keypresses.
-
2
(define-key LaTeX-mode-map (kbd "C-x C-a") (kbd "C-x C-s C-c C-a"))
will work too. Commented Apr 20, 2016 at 13:47 -
-
1A couple of comments: you should wrap the
define-key
in aneval-after-load
; as I said in a previous comment, it's better to runTeX-save-document
rather thansave-buffer
(C-x C-s
).– giordanoCommented Apr 20, 2016 at 14:29 -
Tyler: Strictly speaking,
kbd
returns a keyboard macro, so from that perspective it's a bit odd to differentiate between usingkbd
and using "keyboard macros" (not that interactive recording isn't clearly a different process for producing them).– philsCommented Apr 20, 2016 at 22:55 -
@phils point taken. I hadn't made the connection between keyboard macros (interactively defined) and (kbd ...) before, although it's obvious now. They are still quite distinct user interactions (coding vs recording as you go), and from the perspective worth describing separately i think. If you care to make an edit to clarify this relationship feel free!– TylerCommented Apr 20, 2016 at 23:50
C-c C-a
and notC-x C-a
?TeX-command-run-all
) you can also use the following advice:(advice-add 'TeX-command-run-all :before (lambda (&rest args) (save-buffer)))
in your init file.TeX-save-document
, notsave-buffer
, because it saves all open TeX buffers, not just the current buffer), read the code or test yourself;-)