regexemacselispemacs-faces

Match one backlash; match two backslashes; match tilde + two backslashes


I'm interested in seeing if it is possible to match just 1 backslash, and just 2 backslashes, and a tilde plus two backslashes. I'm using Emacs in latex-mode and am setting up keywords for font-lock. Defining a single backslash as a keyword wreaks havoc on a variety of other definitions. I'd like one backslash to be red; two backslashes to be blue; and a tilde+two-back-slashes to be green. I don't think the tilde will pose a problem, but I'd like that to be red all by itself. I've got the font-lock-add-keywords format, but not the special regex for this type of a situation. This is similar to the situation that we would use \b for before and after, but that won't work with backslashes as far as I know.

~ -- red

\ -- red, except when touching alphanumeric characters.

\\ -- blue

~\\ -- green

(defvar lawlist-face-a (make-face 'lawlist-face-a))
(set-face-attribute 'lawlist-face-a nil :foreground "red" :bold t)

(defvar lawlist-face-b (make-face 'lawlist-face-b))
(set-face-attribute 'lawlist-face-b nil :foreground "blue" :bold t)

(defvar lawlist-face-c (make-face 'lawlist-face-c))
(set-face-attribute 'lawlist-face-c nil :foreground "green" :bold t)

(font-lock-add-keywords 'latex-mode '(

("~\\|\\\\" 0 lawlist-face-a prepend)

("\\\\\\\\" 0 lawlist-face-b prepend)

("~\\\\\\\\" 0 lawlist-face-c prepend)

))

In the context of the example mentioned above, defining a single backslash nullifies the predefined warnings of font-latex.el within auctex-11.86 at lines 280-285. Removing the "\\" from the fourth line of code doesn't remedy the situation. Typing \newpage, for example, no longer is associated with font-latex-warning-face -- instead, it comes up as undefined, which is assigned to font-latex-sedate-face.

(defvar font-latex-built-in-keyword-classes
  '(("warning"
     ("nopagebreak" "pagebreak" "newpage" "clearpage" "cleardoublepage"
      "enlargethispage" "nolinebreak" "linebreak" "newline" "-" "\\*" "\\"
      "appendix" "displaybreak" "allowdisplaybreaks" "include")
     'font-latex-warning-face 1 noarg)

BUFFER EXAMPLE -- latex-mode:

\newpage -- font face should be font-latex-warning-face

\newpage -- font face erroneously appears as font-latex-sedate-face when defining a single backslash as noted hereinabove.


EDIT -- troubleshooting -- testing -- screenshots of re-builder and a LaTeX document:

\\(\\\\\\)[^a-zA-Z@]

re-builder
(source: lawlist.com)

test01
(source: lawlist.com)

(defvar lawlist-face-a (make-face 'lawlist-face-a))
(set-face-attribute 'lawlist-face-a nil :background "black" :foreground "red" :bold t)

(defvar lawlist-face-b (make-face 'lawlist-face-b))
(set-face-attribute 'lawlist-face-b nil :foreground "blue" :bold t)

(defvar lawlist-face-c (make-face 'lawlist-face-c))
(set-face-attribute 'lawlist-face-c nil :foreground "green" :bold t)

(font-lock-add-keywords 'latex-mode
   '(("~\\|\\(\\\\\\)[^a-zA-Z@]" 0 lawlist-face-a prepend)
     ("\\\\\\\\" 0 lawlist-face-b prepend)
     ("~\\\\\\\\" 0 lawlist-face-c prepend)))

test02
(source: lawlist.com)


Solution

  • LaTeX commands can only be composed of letters (and @ symbol in libraries). It is therefore sufficient to do the following to distinguish between a single slash and the beginning of a command:

    (defvar lawlist-face-a (make-face 'lawlist-face-a))
    (set-face-attribute 'lawlist-face-a nil :foreground "red" :bold t)
    
    (defvar lawlist-face-b (make-face 'lawlist-face-b))
    (set-face-attribute 'lawlist-face-b nil :foreground "blue" :bold t)
    
    (defvar lawlist-face-c (make-face 'lawlist-face-c))
    (set-face-attribute 'lawlist-face-c nil :foreground "green" :bold t)
    
    (font-lock-add-keywords 'latex-mode
                            '(("~" 0 lawlist-face-a prepend)
                              ("\\(\\\\\\)[^a-zA-Z@]" 1 lawlist-face-a prepend)
                              ("\\\\\\\\" 0 lawlist-face-b prepend)
                              ("~\\\\\\\\" 0 lawlist-face-c prepend)))