My setup in order to get rid of this fontification annoyance started from giordano's answer but has evolved a little bit as I discovered problems.
What I do
(require 'tex-site) ; Load AUCTeX
(defun my-font-latex-remove-unwanted-fontification-keywords ()
(dolist (command '("newenvironment"
"renewenvironment"
"newcommand"
"renewcommand"
"providecommand"
"fbox"
"mbox"
"sbox"))
(setq-default font-latex-match-function-keywords-local
(remove (assoc-string
command font-latex-match-function-keywords-local)
font-latex-match-function-keywords-local))))
(eval-after-load "font-latex"
'(my-font-latex-remove-unwanted-fontification-keywords))
(defun my-font-latex-add-custom-keywords ()
;; Add our fontification specs for these keywords
(font-latex-add-keywords '(("newenvironment" "*{[[")
("renewenvironment" "*{[[")
("newcommand" "*|{\\[[")
("renewcommand" "*|{\\[[")
("providecommand" "*|{\\[[")
("fbox" "")
("mbox" "")
("sbox" ""))
'function))
(defun my-LaTeX-mode-hook ()
(message "Loading <insert your name here>'s LaTeX mode hook")
;; Use font-latex.el for fontification
(require 'font-latex)
(my-font-latex-add-custom-keywords))
(add-hook 'LaTeX-mode-hook #'my-LaTeX-mode-hook)
- In
~/.emacs.d/auctex/style/xparse.el
:
;; File created by <your name here>. Loaded after, and overrides part of the
;; settings done by xparse.el from the AUCTeX installation.
(TeX-add-style-hook
"xparse"
(lambda ()
(when (and (featurep 'font-latex)
(eq TeX-install-font-lock 'font-latex-setup))
(message "Adding <your name here>'s own keywords for `font-latex' (%s)"
"xparse style file")
(font-latex-add-keywords
'(("DeclareDocumentCommand" "|{\\")
("NewDocumentCommand" "|{\\")
("RenewDocumentCommand" "|{\\")
("ProvideDocumentCommand" "|{\\")
("DeclareExpandableDocumentCommand" "|{\\")
("NewExpandableDocumentCommand" "|{\\")
("RenewExpandableDocumentCommand" "|{\\")
("ProvideExpandableDocumentCommand" "|{\\")
("DeclareDocumentEnvironment" "{")
("NewDocumentEnvironment" "{")
("RenewDocumentEnvironment" "{")
("ProvideDocumentEnvironment" "{"))
'function)))
LaTeX-dialect)
Explanations
Remove built-in keywords we want to redefine
Let's start with the first bit:
(defun my-font-latex-remove-unwanted-fontification-keywords ()
(dolist (command '("newenvironment"
"renewenvironment"
"newcommand"
"renewcommand"
"providecommand"
"fbox"
"mbox"
"sbox"))
(setq-default font-latex-match-function-keywords-local
(remove (assoc-string
command font-latex-match-function-keywords-local)
font-latex-match-function-keywords-local))))
(eval-after-load "font-latex"
'(my-font-latex-remove-unwanted-fontification-keywords))
This is adapted from advice found in the AUCTeX manual. Strictly speaking, and unless I missed something, this part is only required in case some AUCTeX style file would have the strange idea of redeclaring the keywords in question (\newcommand
, \renewcommand
, etc.). Indeed, such style files run after LaTeX-mode-hook
, and therefore can override whatever we do with font-latex-add-keywords
from this hook. Apart from this reason, doing so cleans up (keyword, syntax) pairs from the default value of font-latex-match-function-keywords-local
, so that when I later readd the same keywords with my preferred syntax specification (see below), they occur only once in the resulting value of font-latex-match-function-keywords-local
. Note that:
Since in the end, this code only does setq-default
calls, it doesn't need to be run from the LaTeX-mode-hook
; thus, we save a bit of time doing this way.
I use assoc-string
instead of TeX-assoc-string
(still mentioned in the online AUCTeX manual, but already fixed in the AUCTeX repository) because the latter has been removed from AUCTeX in 2017 (commit d3d321a8d2).
As the AUCTeX manual mentions, since it somehow fiddles with a font-latex
internal, this piece of code is not guaranteed to continue to work as is in future versions of font-latex
.
I apply the same fontification changes to \fbox
, \mbox
and \sbox
as to \newcommand
, \renewcommand
, etc., because in my opinion, the fontification of the argument is no more desirable for these box commands than for \newcommand
and friends.
Redefine fontification specs for the removed built-in keywords
The second bit is essentially the same as in giordano's answer:
(defun my-font-latex-add-custom-keywords ()
;; Add our fontification specs for these keywords
(font-latex-add-keywords '(("newenvironment" "*{[[")
("renewenvironment" "*{[[")
("newcommand" "*|{\\[[")
("renewcommand" "*|{\\[[")
("providecommand" "*|{\\[[")
("fbox" "")
("mbox" "")
("sbox" ""))
'function))
(defun my-LaTeX-mode-hook ()
(message "Loading <insert your name here>'s LaTeX mode hook")
;; Use font-latex.el for fontification
(require 'font-latex)
(my-font-latex-add-custom-keywords))
(add-hook 'LaTeX-mode-hook #'my-LaTeX-mode-hook)
This readds the keywords we just removed, but with my preferred syntax: don't use special colors for the replacement text of macros and environments (see below for an explanation of the "*|{\\[["
syntax).
Note: since my-font-latex-add-custom-keywords
calls font-latex-add-keywords
which, in this particular case, modifies the automatically buffer-local variable font-latex-match-function-keywords-local
, my-font-latex-add-custom-keywords
must be run from buffers where font-latex
is active (buffers in LaTeX mode). This is why I call this function from LaTeX-mode-hook
as opposed to using (eval-after-load "font-latex" ...)
. Indeed, the latter could rerun ...
from any buffer from which (load "font-latex")
is executed, even several times in the same Emacs session—this would set buffer-local variables in the wrong buffer(s).
Override undesirable fontification specs that come from AUCTeX style files
This is the final bit, where we create the file ~/.emacs.d/auctex/style/xparse.el
(see above for its contents). This file takes care of commands defined by xparse such as \NewDocumentCommand
, \NewDocumentEnvironment
, etc. For these, the technique described above doesn't work, because the corresponding font-latex
keywords are not part of font-latex-built-in-keyword-classes
; rather, they are added on-demand by an AUCTeX style file, namely the xparse.el
file that is part of current AUCTeX installations. This particular style file is only activated when your document uses the xparse
package, and the hook it defines (added with TeX-add-style-hook
) is run after LaTeX-mode-hook
. Therefore, calling font-latex-add-keywords
from LaTeX-mode-hook
in order to override syntax specification of LaTeX commands declared in AUCTeX's xparse.el
file doesn't work, since hooks defined in AUCTeX style files are run after LaTeX-mode-hook
.
Fortunately, there is an easy cure: as shown above, all one has to do is to create our own style file as shown above and put it in ~/.emacs.d/auctex/style/
, since it is a hand-written AUCTeX style file (as opposed to ~/.emacs.d/auctex/auto/
, which is for automatically-generated style files1).
Note: my style file for xparse
contains lines such as:
("NewDocumentEnvironment" "{")
The syntax of the second string is explained in the AUCTeX manual. In this case, it tells AUCTeX to only give a special color to the first brace-delimited argument of \NewDocumentEnvironment
. This way, visual attention is only drawn on \NewDocumentEnvironment
and the environment name, so that I get this kind of result:

Had I used this specification instead:
("NewDocumentEnvironment" "{{")
a second argument would have been colorized, like this:

Nothing dramatic, but I believe this is more distracting than helpful (when I browse LaTeX code, I want to quickly see which command or environment starts where; the number and type of its arguments don't need to stand out).
Finally, let's explain the fontification specification for \newcommand
. If you do C-h v font-latex-built-in-keyword-classes
you shoud see a line like this:
("newcommand" "*|{\\[[{")
This means that, by default in the version of AUCTeX used here, \newcommand
is declared to have the following properties:
- it features a star form (
*
);
- the first argument is either (
|
) brace-delimited ({
) or a control sequence token (\
, which must be written as \\
inside an Emacs Lisp string, according to the read syntax for strings defined in the GNU Emacs Lisp Reference Manual);
- the two following arguments are delimited by brackets (
[
, as usual for optional arguments in LaTeX);
- the final argument is delimited by braces (
{
): this is the macro replacement text, which is quite nasty to display all in the same color, in particular a color that makes it difficult to concentrate on. So, by replacing this with:
("newcommand" "*|{\\[[")
we suppress special fontification of the macro replacement text, and by using
("newcommand" "*|{\\")
we would even suppress special fontification of the two optional arguments (however, they are not displayed in a distracting color with "*|{\\[["
, so they don't really bother me).
When style files are not loaded
In some cases, you can have documents that should benefit from a style file, but don't. This may of course cause fontification problems. In order to diagnose this, I examine the *Messages*
buffer after opening or reverting the file in question. If for instance the file has \usepackage{xparse}
but \NewDocumentCommand
isn't fontified as I specified, one can suspect that my xparse.el in ~/.emacs.d/auctex/style/ isn't loaded. This is easy to see thanks to the (message ...)
call I put in this xparse.el. I have the same kind of message when my additions to LaTeX-mode-hook
are run, therefore in such cases, the diagnostic is obtained by seeing the message printed by my additions to LaTeX-mode-hook
but not the one from my own xparse.el.
Now, why would that happen? Well, the style system in AUCTeX isn't very simple, but I figured that what I'm talking about here happens when the name of the .tex (or .sty, .cls...) file I'm working on has the same stem as an already-loaded, non-empty AUCTeX style. For instance, when I call my documents doc.tex, I don't see my xparse fontification even if I have (setq TeX-parse-self t)
in my Emacs initialization file (always) and the document has \usepackage{xparse}
. This is because the AUCTeX style machinery has already loaded a style named doc
, apparently corresponding to tex/latex/base/doc.sty, and therefore AUCTeX mistakenly believes it is not useful to parse my doc.tex (it only records the name doc
in the list of loaded styles TeX-style-hook-list
, and thus can't tell the difference between my doc.tex and the official tex/latex/base/doc.sty).
Another avatar of the same problem can be reproduced by first opening /path/to/unique-filename.tex containing:
\documentclass{article}
\usepackage{xcolor}
\ExplSyntaxOn
\NewDocumentCommand \somecommand { m }
{ }
\ExplSyntaxOff
\begin{document}
\end{document}
(\usepackage{xcolor}
is there to ensure that the AUCTeX style information recorded for unique-filename
won't be empty—there is a check for emptyness of the style information when AUCTeX decides on “should we run TeX-auto-apply
for this file?”)
then opening /path/to/other/unique-filename.tex containing:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \somecommand { m }
{ }
\ExplSyntaxOff
\begin{document}
\end{document}
The first document doesn't have its \NewDocumentCommand
fontified; this is as expected, since it (mistakenly from the LaTeX point of view) doesn't load xparse
. However, the second file also doesn't have its \NewDocumentCommand
fontified, whereas my xparse.el style file says it ought to have. The reason is that when loading or reverting the second file, AUCTeX sees that it has already non-empty style information for unique-filename
(that was loaded for the first unique-filename.tex), and therefore
it doesn't deem it useful to parse the second unique-filename.tex, despite my having set TeX-parse-self
to t
.
In order to work around this, you can set up a key binding that runs a command doing (TeX-run-style-hooks "xparse")
. Actually, since I already have something like the following in my Emacs-wide setup:
(defun my-unconditionally-revert-buffer ()
"Revert buffer from file on disk without asking any question."
(interactive)
(revert-buffer t t))
(put #'my-unconditionally-revert-buffer 'disabled t)
(global-set-key [f5] #'my-unconditionally-revert-buffer)
I have extended it so that the f5
key also runs (TeX-run-style-hooks "xparse")
in LaTeX buffers:
(defun my-unconditionally-revert-buffer-and-rerun-style-hooks ()
(interactive)
(my-unconditionally-revert-buffer)
(dolist (style '("xparse"))
(TeX-run-style-hooks style)))
(put #'my-unconditionally-revert-buffer-and-rerun-style-hooks 'disabled t)
(define-key LaTeX-mode-map [f5]
#'my-unconditionally-revert-buffer-and-rerun-style-hooks)
So, when the problem arises, I first save the buffer, then press f5
to reload the file (not particularly useful after saving) and parse it to gather relevant AUCTeX style information (it gets parsed because I have (setq TeX-parse-self t)
in my Emacs initialization file).
Footnote
- AUCTeX can detect when commands such as
\newcommand
and \newenvironment
are used and automatically generate style information from calls to these commands in your .tex
or .sty
files (also .cls
, .ltx
, .dtx
and others; see Automatic Customization in the AUCTeX manual, the TeX-file-extensions
variable and the TeX-auto-generate
AUCTeX command).
\chapter
command in a\newcommand
is formatted like it were in text. – egreg Jun 24 '13 at 8:28\chapter
is bigger; that's what I was referring to. – egreg Jun 24 '13 at 10:07\chapter
's argument would have to depend on the context. – John Wickerson Jun 24 '13 at 10:15