1

When I have text inside \begin{equation} ... \end{equation}, font-latex-math-face face is applied.

If I have atikzpicture block inside equation, font-latex-math-face face is applied to it as well:

\begin{equation} 
    \begin{tikzpicture}
        ... % font-latex-math-face is applied, which I don't want 
    \end{tikzpicture}
\end{equation}

Is it possible to prevent font-latex-math-face from being applied to the tikzpicture block even though it's inside the equation block?

Related: https://emacs.stackexchange.com/a/30427/18414

3 Answers 3

1
+50

Sample demo.tex file that has tikzpicture within a equation

% Created 2022-10-14 Fri 14:48
% Intended LaTeX compiler: pdflatex
\documentclass[11pt]{article}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{graphicx}
\usepackage{longtable}
\usepackage{wrapfig}
\usepackage{rotating}
\usepackage[normalem]{ulem}
\usepackage{amsmath}
\usepackage{amssymb}
\usepackage{capt-of}
\usepackage{hyperref}
\usepackage{tikz}
\date{\today}
\title{}
\hypersetup{
 pdftitle={},
 pdfkeywords={},
 pdfsubject={},
 pdfcreator={Emacs 29.0.50 (Org mode 9.5.5)}, 
 pdflang={English}}
\begin{document}

\tableofcontents

\begin{equation}
\begin{tikzpicture}[baseline=(current  bounding  box.center)]
\node {sqrt} % root
  child { node {sqrt-iter}
                  child[sibling distance=5cm] { node{ good-enough }
                          child[sibling distance=2cm] { node { square } }
                          child[sibling distance=2cm] { node { abs } } }
                  child { node{ improve }
                          child { node { average } } } };
\end{tikzpicture}
\end{equation}  

\begin{equation} 
  x=\sqrt{b}
\end{equation}   

If \(a^2=b\) and \(b=2\), then the solution must be
either $$ a=+\sqrt{2} $$ or \[ a=-\sqrt{2} \].

\end{document}



How the above tex file is rendered

PDF view of above tex file

How the buffer looks like in emacs -Q

tikzpicture within equation environment gets a font-latex-math-face

tikzpicture within equation environment gets a font-latex-math-face

Copy the following snippet to *scratch*, and do M-x eval-buffer.

(add-hook 'LaTeX-mode-hook
          (defun my-LaTeX-mode-hook ()
            (hi-lock-mode 1)
            (highlight-regexp
             (rx (seq
                  "\\begin{tikzpicture}"
                  "[" (group (one-or-more any)) "]"
                  (group (minimal-match (one-or-more (or any "\n"))))
                  "\\end{tikzpicture}"))
             'hi-yellow 2)
            (font-lock-flush))
          t)

Visit the above demo.tex and do M-x revert-buffer. This is how it looks

tikzpicture gets its own face (which is hi-yellow)

tikzpicture gets its own face (which is hi-yellow)

To highlight tikzpicture in default face, change 'hi-yellow in the snippet to 'default.


When I open the .tex file, and I do C-h m I get

The major mode is LaTeX/P mode defined in tex-mode.el:

This function has :override advice: TeX-latex-mode.

This is an :override advice, which means that latex-mode isn’t run at all, and the documentation below may be irrelevant.

I also see

TeX-latex-mode is an autoloaded interactive byte-compiled Lisp function in latex.el.

(TeX-latex-mode)

Major mode in AUCTeX for editing LaTeX files. See info under AUCTeX for full documentation.

I had trouble finding the relevant hook. You may have to find what hook is run in your case. See https://git.savannah.gnu.org/cgit/emacs/elpa.git/tree/latex.el?h=b91f15b3a375445985143ed1d6e41490ea62780a#n7161. As the screenshots, there is no problem with the snippet. May be our running environments are different. May be try putting it on TeX-mode-hook.

To test the snippet, you don't have to have to put it on a hook. Just add an interactive spec to my-LaTeX-mode-hook, and call the function with M-x ....

(I am not a tex user, auctex is one of the big old packages which was outside of Emacs for a long time. So, it has plenty of "hacks")

4
  • What is TeX-latex-mode-hook-79i7rxb01mj ? like where did 79i7rxb01mj0 come from?
    – alper
    Oct 14, 2022 at 22:51
  • When I try to add the function into configu file i am getting follwing error: Debugger entered--Lisp error: (error "‘TeX-latex-mode-hook-79i7rxb01mj0’ is not a valid ...") signal(error ("‘TeX-latex-mode-hook-79i7rxb01mj0’ is not a valid ..."))
    – alper
    Oct 14, 2022 at 22:57
  • See the bottom of my previous answer.
    – user31220
    Oct 15, 2022 at 1:12
  • Originally inside tikzpicuture font-latex-sedate-face is assigned for the \node (makes it bold and different color) to obtain this instead of 'default do you have an idea what should be used?
    – alper
    Oct 16, 2022 at 11:24
1

https://emacs.stackexchange.com/a/30427/18414

The suggestion here is good enough.

By default, the font-latex-verbatim-face and font-latex-math-face pick up the same color on X.

(With the same color assigned to math and verbatim environment, it is easy to mistake that the verbatim environment is not working)

Similarly, in my earlier screenshot sedate face is left unconfigured. Once you configure it, it is possible to distinguish between the equation, tikzpicture and sedate environments by carefull choosing the face properties.

(For example, in the config below, the sedate face has a bold property; even thought its :foreground property is overridden by verbatim face, the extra bold property makes it standout.)

Here is the screenshot

tikzpicture in math environment

tikzpicture in math environment

taken with

(TeX-load-hack)

(custom-set-variables
 '(LaTeX-verbatim-environments
   '("verbatim" "verbatim*" "filecontents" "filecontents*" "tikzpicture")))

(custom-set-faces
 '(font-latex-sedate-face ((t (:foreground "DarkOrange" :weight bold))))
 '(font-latex-verbatim-face ((t (:inherit fixed-pitch :foreground "turquoise"))))
 '(my-tikzpicture-face ((t (:foreground "ForestGreen"))) t))


My earlier suggestion is superior to the verbatim environment because you can the tikzpicture can have its own color different from verbatim environments.

To get this

tikzpicture gets its own face---that is tikzpicture is not using verbatim environment here

tikzpicture gets its own face

do this


(TeX-load-hack)

(add-hook 'LaTeX-mode-hook
          (defun TeX-latex-mode-hook-79i7rxb01mj0 ()
            (message "coming hree")
            (hi-lock-mode 1)
            (highlight-regexp
             (rx (seq
                  "\\begin{tikzpicture}"
                  (group (optional "[" (one-or-more any) "]"))
                  (group (minimal-match (zero-or-more (or any "\n"))))
                  "\\end{tikzpicture}"))
             'my-tikzpicture-face 2)
            (font-lock-flush))
          t)

(defface my-tikzpicture-face nil
  "Face for tikzpicture environment."
  :group 'font-latex-highlighting-faces)

(custom-set-faces
 '(font-latex-sedate-face ((t (:foreground "DarkOrange" :weight bold))))
 '(font-latex-verbatim-face ((t (:inherit fixed-pitch :foreground "turquoise"))))
 '(my-tikzpicture-face ((t (:foreground "ForestGreen"))) t))
0

BUYER BEWARE!!!

This is an experimental code ... Please don't use it in an Emacs session in which you are editing important documents like dissertation. If there are bugs in the font-lock matcher, it will lock up your Emacs, and you need to essentially restart Emacs, and lose all the edits.

A Bird's eye view of the snippet

What you want here is fontification of tikzpicture environment apart from its parent environment, equation in this case.

This scenario occurs in org-mode. For example, the src-blocks are fontified using their own environment, apart from the surrounding org-mode environment.

IOW, conceptually

  • tikzpicture env => #+begin_src ... #+end_src
  • equation env => org-mode

So, in the snippet below, the tikzpicture environment is copied over to temporary buffer in latex-mode, fontified there, and its face properties transferred over to the original tex buffer. This is exactly what the org-mode does while fontifying src-blocks natively.

IOW, the snippet is a verbatim copy of org-mode src-block fontification code, but to cater to the current requirements.

A Challenge: "Partial" or "Delayed" fontification is observed; but not addressed

org-mode and auctex aren't same, and their fontification defaults are different ... So, for some reasons while using this code there will be partial fontification of tikzpicture blocks, which will go away as soon as you issue a command.

(My font-lock-fu is not good enough to address this "partial fontification" issue.)

That said, here is the real meat ...

To get this

Fontify tikzpicture environment independently of its surrrounding math environment

Fontify tikzpicture environment independently of its surrrounding math environment

(Its worth comparing the screenshot here with screenshots provided in earlier answers. Note specifically the order of faces in tikzpicture environment)

do this

(require 'tex-site)

(defface my-tikzpicture-face nil
  "Face for tikzpicture environment."
  :group 'font-latex-highlighting-faces)

(custom-set-faces
 '(font-latex-sedate-face ((t (:foreground "DarkOrange" :weight bold))))
 '(font-latex-verbatim-face ((t (:inherit fixed-pitch :foreground "turquoise"))))
 '(my-tikzpicture-face ((t (:foreground "ForestGreen"))) t))

(defvar-local suppress-my-tikzpicture-matcher nil)

(defun my-tikzpicture-matcher (limit)
  ;; (message "tikzpicture-matcher: %S" limit)
  (unless suppress-my-tikzpicture-matcher
    (let ((case-fold-search t))
      (while (re-search-forward
              (rx (seq
                   "\\begin{tikzpicture}"
                   (optional "[" (minimal-match (one-or-more any)) "]")
                   (group (minimal-match (zero-or-more (or any "\n"))))
                   "\\end{tikzpicture}"))
              limit t)
        (let ((start (match-beginning 0))
              (end (match-end 0))
              (lang 'latex-mode))
          (add-text-properties start end
                               '(font-lock-fontified t font-lock-multiline t))

          (let ((lang-mode 'latex-mode))
            (when (fboundp lang-mode)
              (let ((string (buffer-substring-no-properties start end))
                    (modified (buffer-modified-p))
                    (tex-buffer (current-buffer)))
                (remove-text-properties start end '(face nil))
                (font-lock-prepend-text-property start end 'face 'my-tikzpicture-face tex-buffer)
                (with-current-buffer
                    (get-buffer-create
                     (format " *tikzpicture fontification:%s [%s %s]*" lang-mode start end))
                  (setq suppress-my-tikzpicture-matcher t)
                  (let ((inhibit-modification-hooks nil))
                    (erase-buffer)
                    ;; Add string and a final space to ensure property change.
                    (insert string " "))
                  (unless (eq major-mode lang-mode) (funcall lang-mode))
                  (font-lock-ensure)
                  (let ((pos (point-min)) next)
                    (while (setq next (next-property-change pos))
                      ;; Handle additional properties from font-lock, so as to
                      ;; preserve, e.g., composition.
                      (dolist (prop (cons 'face font-lock-extra-managed-props))
                        (let ((new-prop (get-text-property pos prop)))
                          (font-lock-prepend-text-property
                           (+ start (1- pos)) (1- (+ start next)) prop new-prop
                           tex-buffer)
                          ;; (put-text-property
                          ;;  (+ start (1- pos)) (1- (+ start next)) prop new-prop
                          ;;  tex-buffer)
                          ))
                      (setq pos next))))
                (add-text-properties start end
                                     '(
                                       font-lock-fontified t
                                       fontified t
                                       font-lock-multiline t))

                (set-buffer-modified-p modified))))))
      (force-window-update (current-buffer))
      nil)))

;; (run-mode-hooks 'text-mode-hook 'TeX-mode-hook 'LaTeX-mode-hook)
(add-hook 'LaTeX-mode-hook
          (defun my-LaTeX-mode-hook ()
            (font-lock-add-keywords nil
                                    (list '(my-tikzpicture-matcher))
                                    'append)
            (font-lock-flush)))

3
  • If you make my-tikzpicture-face inherit from default face, you will no longer notice that tikzpicture is within the math environment (custom-set-faces '(my-tikzpicture-face ((t (:inherit default))) t)). This is experimental code---but most of it is derived from well-worn org-mode code---so use it with some caution.
    – user31220
    Oct 17, 2022 at 4:35
  • There are 3 answers of yours, which one should I use?
    – alper
    Oct 17, 2022 at 16:45
  • My recommendations from most reliable to the least: Use verbatim blocks (Solution 2). it is the code which is already there in latex. Uses highlight-regexp (Solution 1). Amount of custom code is minimal. Use custom fontifier (Solution 3): Lots of custom code, and there are some delays in fontification.
    – user31220
    Oct 18, 2022 at 1:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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