7

The syntax highlighting for \newcommand in my editor (Aquamacs/AucTeX) looks like this:

enter image description here

I don't like it because everything inside the definition has the same light blue colour. By contrast, if I use a \def instead, I get the following highlighting, which I much prefer.

enter image description here

According to the AucTeX manual, §3.1.1, AucTeX keeps a list of "function" keywords in the variable font-latex-match-function-keywords. It currently contains: begin, end, pagenumbering, thispagestyle, pagestyle, nofiles, includeonly, bibliographystyle, documentstyle, documentclass, newcommand, newenvironment, newlength, newtheorem, newcounter, renewenvironment, renewcommand, renewtheorem, usepackage, fbox, mbox, sbox, vspace, hspace, thinspace, negthinspace, enspace, enskip, quad, qquad, nonumber, centering, TeX, LaTeX.

I would like to remove from that list all those commands that tend to take long arguments, namely: newenvironment, renewenvironment, newcommand, renewcommand, fbox, mbox and sbox. What LISP instructions can I put into my .emacs file to do that?

  • To me, the most annoying feature is that a \chapter command in a \newcommand is formatted like it were in text. – egreg Jun 24 '13 at 8:28
  • Oh? I don't have that problem: see i.stack.imgur.com/nnbPj.png – John Wickerson Jun 24 '13 at 9:56
  • The "foo" in the argument of \chapter is bigger; that's what I was referring to. – egreg Jun 24 '13 at 10:07
  • Oh, I'm with you now. Yeah, I guess it might be tricky to fix that. The highlighting of \chapter's argument would have to depend on the context. – John Wickerson Jun 24 '13 at 10:15
  • There is an AUCTeX function to check whether point is inside the argument of a macro, but I don't know where to put this check, actually I'm not comfortable with font locking hacking in Emacs. – giordano Jun 24 '13 at 10:26
10

The solution is to override built-in fontification with what you want. You can do that using the font-latex-add-keywords function. For more information about the argument specification, see Fontification of macros in the AUCTeX manual.

To change fontification of the macros you mentioned, you can add this to your .emacs:

(defun my-font-latex-add-custom-keywords ()
  (eval-after-load "font-latex"
    '(font-latex-add-keywords '(("newenvironment" "*{[[")
                                ("renewenvironment" "*{[[")
                                ("newcommand" "*|{\\[[")
                                ("renewcommand" "*|{\\[[")
                                ("providecommand" "*|{\\[[")
                                ("fbox" "")
                                ("mbox" "")
                                ("sbox" ""))
                              'function)))

(add-hook 'LaTeX-mode-hook 'my-font-latex-add-custom-keywords)
  • One minor improvement could be to fontify the first argument of, say, \newcommand, but not the second. So \newcommand\john{blahblah} would highlight the \john but not the blahblah. My guess is this could be done quite easily by modifying the current entry ("newcommand" "*|{\\[[{") in font-latex-match-function-keywords-local. But I don't know how to do this. – John Wickerson Jun 24 '13 at 10:45
  • Answer updated. I changed the fontification definitions removing the last { from all of them. – giordano Jun 24 '13 at 11:12
1

You can customize the Font Lock Function Name Face (font-lock-function-name-face):

  • M-x customize-face
  • Choose font-lock-function-name-face
  • Uncheck Foreground
  • Press Save for future sessions button
  • This changes only the face of the function name (for all Emacs modes, not just AUCTeX), not fontification of arguments. – giordano Jun 24 '13 at 11:18
  • @giordano In my versions of AUCTeX (11.87) and Emacs (23.4.1), this changes the color of the function and the aspect of the code of the function... – Paul Gaborit Jun 24 '13 at 11:36
  • Ok, you're right, but it isn't what John asked for. – giordano Jun 24 '13 at 11:40
  • Thanks Paul, that's a nice alternative approach. I'll stick with Giordano's approach because it allows fine-grained control over exactly which parts are highlighted and which aren't. – John Wickerson Jun 24 '13 at 11:56
1

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:

Screenshot with good fontification

Had I used this specification instead:

("NewDocumentEnvironment" "{{")

a second argument would have been colorized, like this:

Screenshot with bad (too much) fontification

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

  1. 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).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.