[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[AUCTeX-diffs] Changes to auctex/font-latex.el [multiline-font-lock]
From: |
Ralf Angeli |
Subject: |
[AUCTeX-diffs] Changes to auctex/font-latex.el [multiline-font-lock] |
Date: |
Mon, 27 Mar 2006 09:18:00 +0000 |
Index: auctex/font-latex.el
diff -u /dev/null auctex/font-latex.el:5.147.2.1
--- /dev/null Mon Mar 27 09:18:00 2006
+++ auctex/font-latex.el Mon Mar 27 09:18:00 2006
@@ -0,0 +1,1669 @@
+;;; font-latex.el --- LaTeX fontification for Font Lock mode.
+
+;; Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+;; 2004, 2005, 2006 Free Software Foundation.
+
+;; Authors: Peter S. Galbraith <address@hidden>
+;; Simon Marshall <address@hidden>
+;; Maintainer: address@hidden
+;; Created: 06 July 1996
+;; Keywords: tex, wp, faces
+
+;;; This file is not part of GNU Emacs.
+
+;; This package is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This package is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; This package enhances font-lock fontification patterns for LaTeX.
+;; font-lock mode is a minor mode that causes your comments to be
+;; displayed in one face, strings in another, reserved words in
+;; another, and so on.
+;;
+;; ** Infinite loops !? **
+;; If you get an infinite loop, send a bug report!
+;; Then set the following in your ~/.emacs file to keep on working:
+;; (setq font-latex-do-multi-line nil)
+
+;;; Code:
+
+(require 'font-lock)
+(require 'tex)
+
+(eval-when-compile
+ (require 'cl))
+
+(defgroup font-latex nil
+ "Font-latex text highlighting package."
+ :prefix "font-latex-"
+ :group 'faces
+ :group 'tex
+ :group 'AUCTeX)
+
+(defgroup font-latex-keywords nil
+ "Keywords for highlighting text in font-latex."
+ :prefix "font-latex-"
+ :group 'font-latex)
+
+(defgroup font-latex-highlighting-faces nil
+ "Faces for highlighting text in font-latex."
+ :prefix "font-latex-"
+ :group 'font-latex)
+
+(defcustom font-latex-do-multi-line t
+ "Control multi-line fontification.
+
+Emacs provides its own facilities for multi-line fontification
+which can be controlled by the variable `font-lock-multiline'.
+
+Setting `font-latex-do-multi-line' to a non-nil value will enable
+this mechanism if it is available.
+
+Setting this variable will only have effect after resetting
+buffers controlled by font-latex or restarting Emacs."
+ :group 'font-latex
+ :type 'boolean)
+
+(defvar font-latex-multiline-boundary 5000
+ "Size of region to search for the start or end of a multiline construct.")
+
+(defvar font-latex-quote-regexp-beg nil
+ "Regexp used to find quotes.")
+
+(defvar font-latex-quote-list '(("``" "''") ("<<" ">>" french) ("«" "»"
french))
+ "List of quote specifiers for quotation fontification.
+
+Each element of the list is either a list consisting of two
+strings to be used as opening and closing quotation marks
+independently of the value of `font-latex-quotes' or a list with
+three elements where the first and second element are strings for
+opening and closing quotation marks and the third element being
+either the symbol 'german or 'french describing the order of
+quotes.
+
+If `font-latex-quotes' specifies a different state, order of the
+added quotes will be reversed for fontification. For example if
+'(\"\\\"<\" \"\\\">\" french) is given but `font-latex-quotes'
+specifies 'german, quotes will be used like \">foo\"< for
+fontification.")
+
+(defvar font-latex-quotes-control nil
+ "Internal variable for keeping track if `font-latex-quotes' changed.")
+
+(defcustom font-latex-quotes 'french
+ "Whether to fontify << French quotes >> or >>German quotes<<.
+Also selects \"<quote\"> versus \">quote\"<."
+ :type '(choice (const french) (const german))
+ :group 'font-latex)
+
+(defun font-latex-add-quotes (quotes)
+ "Add QUOTES to `font-latex-quote-list'.
+QUOTES has to be a list adhering to the format of an element of
+`font-latex-quote-list'."
+ (set (make-local-variable 'font-latex-quotes-control) nil)
+ (make-local-variable 'font-latex-quote-list)
+ (add-to-list 'font-latex-quote-list quotes))
+
+;; The definitions of the title faces were originally taken from
+;; info.el (Copyright (C) 1985, 86, 92, 93, 94, 95, 96, 97, 98, 99,
+;; 2000, 2001 Free Software Foundation, Inc.) and adapted to the needs
+;; of font-latex.el.
+
+(defconst font-latex-sectioning-max 5
+ "Highest number for font-latex-sectioning-N-face")
+(defface font-latex-sectioning-5-face
+ (if (featurep 'xemacs)
+ '((((type tty pc) (class color) (background light))
+ (:foreground "blue4" :bold t))
+ (((type tty pc) (class color) (background dark))
+ (:foreground "yellow" :bold t))
+ (((class color) (background light))
+ (:bold t :foreground "blue4" :family "helvetica"))
+ (((class color) (background dark))
+ (:bold t :foreground "yellow" :family "helvetica"))
+ (t (:bold t :family "helvetica")))
+ '((((type tty pc) (class color) (background light))
+ (:foreground "blue4" :weight bold))
+ (((type tty pc) (class color) (background dark))
+ (:foreground "yellow" :weight bold))
+ (((class color) (background light))
+ (:weight bold :inherit variable-pitch :foreground "blue4"))
+ (((class color) (background dark))
+ (:weight bold :inherit variable-pitch :foreground "yellow"))
+ (t (:weight bold :inherit variable-pitch))))
+ "Face for sectioning commands at level 5."
+ :group 'font-latex-highlighting-faces)
+
+(defun font-latex-update-sectioning-faces (&optional max height-scale)
+ "Update sectioning commands faces."
+ (unless height-scale
+ (setq height-scale (if (numberp font-latex-fontify-sectioning)
+ font-latex-fontify-sectioning
+ 1.1)))
+ (unless max
+ (setq max font-latex-sectioning-max))
+ (dotimes (num max)
+ (let* (;; reverse for XEmacs:
+ (num (- max (1+ num)))
+ (face-name (intern (format "font-latex-sectioning-%s-face" num))))
+ (unless (get face-name 'saved-face) ; Do not touch customized faces.
+ (if (featurep 'xemacs)
+ (let ((size
+ ;; Multiply with .9 because `face-height' returns a value
+ ;; slightly larger than the actual font size.
+ ;; `make-face-size' takes numeric points according to Aidan
+ ;; Kehoe in <address@hidden> (not
+ ;; documented).
+ (round (* 0.9
+ (face-height 'default)
+ (expt height-scale (- max 1 num))))))
+ ;; (message "%s - %s" face-name size)
+ (make-face-size face-name size))
+ (set-face-attribute face-name nil :height height-scale))))))
+
+(defcustom font-latex-fontify-sectioning 1.1
+ "Whether to fontify sectioning macros with varying height or a color face.
+
+If it is a number, use varying height faces. The number is used
+for scaling starting from `font-latex-sectioning-5-face'. Typically
+values from 1.05 to 1.3 give best results, depending on your font
+setup. If it is the symbol `color', use `font-lock-type-face'.
+
+Caveats: Customizing the scaling factor applies to all sectioning
+faces unless those face have been saved by customize. Setting
+this variable directly does not take effect unless you call
+`font-latex-update-sectioning-faces' or restart Emacs.
+
+Switching from `color' to a number or vice versa does not take
+effect unless you call \\[font-lock-fontify-buffer] or restart
+Emacs."
+ ;; Possibly add some words about XEmacs here. :-(
+ :type '(choice (number :tag "Scale factor")
+ (const color))
+ :initialize 'custom-initialize-default
+ :set (lambda (symbol value)
+ (set-default symbol value)
+ (unless (eq value 'color)
+ (font-latex-update-sectioning-faces font-latex-sectioning-max
value)))
+ :group 'font-latex)
+
+(defun font-latex-make-sectioning-faces (max &optional height-scale)
+ "Build the faces used to fontify sectioning commands."
+ (unless max (setq max font-latex-sectioning-max))
+ (unless height-scale
+ (setq height-scale (if (numberp font-latex-fontify-sectioning)
+ font-latex-fontify-sectioning
+ 1.1)))
+ (dotimes (num max)
+ (let* (;; reverse for XEmacs:
+ (num (- max (1+ num)))
+ (face-name (intern (format "font-latex-sectioning-%s-face" num)))
+ (f-inherit (intern (format "font-latex-sectioning-%s-face" (1+
num))))
+ (size (when (featurep 'xemacs)
+ (round (* 0.9 (face-height 'default)
+ (expt height-scale (- max 1 num)))))))
+ (eval
+ `(defface ,face-name
+ (if (featurep 'xemacs)
+ '((t (:size ,(format "%spt" size))))
+ '((t (:height ,height-scale :inherit ,f-inherit))))
+ (format "Face for sectioning commands at level %s.
+
+Probably you don't want to customize this face directly. Better
+change the base face `font-latex-sectioning-5-face' or customize the
+variable `font-latex-fontify-sectioning'." num)
+ :group 'font-latex-highlighting-faces))
+ (when (and (featurep 'xemacs)
+ ;; Do not touch customized faces.
+ (not (get face-name 'saved-face)))
+ (set-face-parent face-name f-inherit)
+ ;; Explicitely set the size again to code around the bug that
+ ;; `set-face-parent' overwrites the original face size.
+ (make-face-size face-name size)))))
+
+(font-latex-make-sectioning-faces font-latex-sectioning-max)
+
+
+;;; Keywords
+
+(defvar font-latex-keywords-1 nil
+ "Subdued level highlighting for LaTeX modes.")
+
+(defvar font-latex-keywords-2 nil
+ "High level highlighting for LaTeX modes.")
+
+(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)
+ ("variable"
+ (("setlength" "{}{}") ("settowidth" "{}{}") ("setcounter" "{}{}")
+ ("addtolength" "{}{}") ("addtocounter" "{}{}"))
+ 'font-lock-variable-name-face 2 command)
+ ("reference"
+ (("nocite" "{}") ("cite" "[]{}") ("label" "{}") ("pageref" "{}")
+ ("vref" "{}") ("eqref" "{}") ("ref" "{}") ("include" "{}")
+ ("input" "{}") ("bibliography" "{}") ("index" "{}") ("glossary" "{}")
+ ("footnote" "[]{}") ("footnotemark" "[]") ("footnotetext" "[]{}"))
+ 'font-lock-constant-face 2 command)
+ ("function"
+ (("begin" "{}") ("end" "{}") ("pagenumbering" "{}")
+ ("thispagestyle" "{}") ("pagestyle" "{}") ("nofiles" "")
+ ("includeonly" "{}") ("bibliographystyle" "{}") ("documentstyle" "[]{}")
+ ("documentclass" "[]{}") ("newenvironment" "*{}[][]{}{}")
+ ("newcommand" "*{}[][]{}") ("newlength" "{}") ("newtheorem" "{}[]{}[]")
+ ("newcounter" "{}[]") ("renewenvironment" "*{}[]{}{}")
+ ("renewcommand" "*{}[][]{}") ("renewtheorem" "{}[]{}[]")
+ ("usepackage" "[]{}") ("fbox" "{}") ("mbox" "{}") ("sbox" "{}")
+ ("vspace" "*{}") ("hspace" "*{}") ("thinspace" "") ("negthinspace" "")
+ ;; XXX: Should macros without arguments rather be listed in a
+ ;; separate category with 'noarg instead of 'command handling?
+ ("enspace" "") ("enskip" "") ("quad" "") ("qquad" "") ("nonumber" "")
+ ("centering" "") ("TeX" "") ("LaTeX" ""))
+ 'font-lock-function-name-face 2 command)
+ ("sectioning-0"
+ (("part" "*[]{}"))
+ (if (eq font-latex-fontify-sectioning 'color)
+ 'font-lock-type-face
+ 'font-latex-sectioning-0-face)
+ 2 command)
+ ("sectioning-1"
+ (("chapter" "*[]{}"))
+ (if (eq font-latex-fontify-sectioning 'color)
+ 'font-lock-type-face
+ 'font-latex-sectioning-1-face)
+ 2 command)
+ ("sectioning-2"
+ (("section" "*[]{}"))
+ (if (eq font-latex-fontify-sectioning 'color)
+ 'font-lock-type-face
+ 'font-latex-sectioning-2-face)
+ 2 command)
+ ("sectioning-3"
+ (("subsection" "*[]{}"))
+ (if (eq font-latex-fontify-sectioning 'color)
+ 'font-lock-type-face
+ 'font-latex-sectioning-3-face)
+ 2 command)
+ ("sectioning-4"
+ (("subsubsection" "*[]{}"))
+ (if (eq font-latex-fontify-sectioning 'color)
+ 'font-lock-type-face
+ 'font-latex-sectioning-4-face)
+ 2 command)
+ ("sectioning-5"
+ (("paragraph" "*[]{}") ("subparagraph" "*[]{}")
+ ("subsubparagraph" "*[]{}"))
+ (if (eq font-latex-fontify-sectioning 'color)
+ 'font-lock-type-face
+ 'font-latex-sectioning-5-face)
+ 2 command)
+ ("slide-title" () 'font-latex-slide-title-face 2 command)
+ ("textual"
+ (("item" "[]") ("title" "{}") ("author" "{}") ("date" "{}")
+ ("thanks" "{}") ("address" "{}") ("caption" "[]{}")
+ ("textsuperscript" "{}"))
+ 'font-lock-type-face 2 command)
+ ("bold-command"
+ (("textbf" "{}") ("textsc" "{}") ("textup" "{}") ("boldsymbol" "{}")
+ ("pmb" "{}"))
+ 'font-latex-bold-face 1 command)
+ ("italic-command"
+ (("emph" "{}") ("textit" "{}") ("textsl" "{}"))
+ 'font-latex-italic-face 1 command)
+ ("math-command"
+ (("ensuremath" "{}"))
+ 'font-latex-math-face 1 command)
+ ("type-command"
+ (("texttt" "{}") ("textsf" "{}") ("textrm" "{}") ("textmd" "{}"))
+ 'font-lock-type-face 1 command)
+ ("bold-declaration"
+ ("bf" "bfseries" "sc" "scshape" "upshape")
+ 'font-latex-bold-face 1 declaration)
+ ("italic-declaration"
+ ("em" "it" "itshape" "sl" "slshape")
+ 'font-latex-italic-face 1 declaration)
+ ("type-declaration"
+ ("tt" "ttfamily" "sf" "sffamily" "rm" "rmfamily" "mdseries"
+ "tiny" "scriptsize" "footnotesize" "small" "normalsize"
+ "large" "Large" "LARGE" "huge" "Huge")
+ 'font-lock-type-face 1 declaration))
+ "Built-in keywords and specifications for font locking.
+
+The first element of each item is the name of the keyword class.
+
+The second element is a list of keywords (macros without an
+escape character) to highlight or, if the fifth element is the
+symbol 'command, a list of lists where the first element of each
+item is a keyword and the second a format specifier depicting the
+sequence of optional (\"[]\") and mandatory (\"{}\") arguments of
+a LaTeX macro.
+
+The third element is the symbol of a face to be used or a Lisp
+form returning a face symbol.
+
+The fourth element is the fontification level.
+
+The fifth element is the type of construct to be matched. It can
+be one of 'noarg which will match simple macros without
+arguments (like \"\\foo\"), 'declaration which will match macros
+inside a TeX group (like \"{\\bfseries foo}\"), or 'command which
+will match macros of the form \"\\foo[bar]{baz}\".")
+
+(defcustom font-latex-deactivated-keyword-classes nil
+ "List of strings for built-in keyword classes to be deactivated.
+
+Valid entries are \"warning\", \"variable\", \"reference\",
+\"function\" , \"sectioning-0\", \"sectioning-1\", \"sectioning-2\",
+\"sectioning-3\", \"sectioning-4\", \"sectioning-5\", \"textual\",
+\"bold-command\", \"italic-command\", \"math-command\", \"type-command\",
+\"bold-declaration\", \"italic-declaration\", \"type-declaration\".
+
+You have to restart Emacs for a change of this variable to take effect."
+ :group 'font-latex-keywords
+ :type `(set ,@(mapcar
+ (lambda (spec)
+ `(const :tag ,(concat
+ ;; Name of the keyword class
+ (let ((name (split-string (car spec) "-")))
+ (setcar name (capitalize (car name)))
+ (mapconcat 'identity name " "))
+ " keywords in `"
+ ;; Name of the face
+ (symbol-name (eval (nth 2 spec))) "'.\n"
+ ;; List of keywords
+ (with-temp-buffer
+ (insert " Keywords: "
+ (mapconcat (lambda (x)
+ (if (listp x)
+ (car x)
+ x))
+ (nth 1 spec) ", "))
+ (fill-paragraph nil)
+ (buffer-substring-no-properties
+ (point-min) (point-max))))
+ ,(car spec)))
+ font-latex-built-in-keyword-classes)))
+
+(defun font-latex-make-match-defun (prefix name face type)
+ "Return a function definition for keyword matching.
+The variable holding the keywords to match are determined by the
+strings PREFIX and NAME. The type of matcher is determined by
+the symbol TYPE.
+
+This is a helper function for `font-latex-make-built-in-keywords'
+and `font-latex-make-user-keywords' and not intended for general
+use."
+ ;; Note: The functions are byte-compiled at the end of font-latex.el.
+ ;; FIXME: Is the cond-clause possible inside of the defun?
+ (cond ((eq type 'command)
+ (eval `(defun ,(intern (concat prefix name)) (limit)
+ ,(concat "Fontify `" prefix name "' up to LIMIT.
+
+Generated by `font-latex-make-match-defun'.")
+ (when ,(intern (concat prefix name))
+ (font-latex-match-command-with-arguments
+ ,(intern (concat prefix name))
+ (append
+ (when (boundp ',(intern (concat prefix name
+ "-keywords-local")))
+ ,(intern (concat prefix name "-keywords-local")))
+ ,(intern (concat prefix name "-keywords")))
+ ;; `face' can be a face symbol, a form returning
+ ;; a face symbol, or a list of face attributes.
+ (if (and (listp ,face) (functionp (car ,face)))
+ (eval ,face)
+ ,face)
+ limit)))))
+ ((eq type 'declaration)
+ (eval `(defun ,(intern (concat prefix name)) (limit)
+ ,(concat "Fontify `" prefix name "' up to LIMIT.
+
+Generated by `font-latex-make-match-defun'.")
+ (when ,(intern (concat prefix name))
+ (font-latex-match-command-in-braces
+ ,(intern (concat prefix name)) limit)))))
+ ((eq type 'noarg)
+ (eval `(defun ,(intern (concat prefix name)) (limit)
+ ,(concat "Fontify `" prefix name "' up to LIMIT.
+
+Generated by `font-latex-make-match-defun'.")
+ (when ,(intern (concat prefix name))
+ (re-search-forward
+ ,(intern (concat prefix name)) limit t)))))))
+
+(defun font-latex-keyword-matcher (prefix name face type)
+ "Return a matcher and highlighter as required by `font-lock-keywords'.
+PREFIX and NAME are strings which are concatenated to form the
+respective match function. FACE is a face name or a list of text
+properties that will be applied to the respective part of the
+match returned by the match function. TYPE is the type of
+construct to be highlighted. Currently the symbols 'command,
+'sectioning, 'declaration and 'noarg are valid.
+
+This is a helper function for `font-latex-make-built-in-keywords'
+and `font-latex-make-user-keywords' and not intended for general
+use."
+ (cond ((eq type 'command)
+ `(,(intern (concat prefix name))
+ (0 (font-latex-matched-face 0) append t)
+ (1 (font-latex-matched-face 1) append t)
+ (2 (font-latex-matched-face 2) append t)
+ (3 (font-latex-matched-face 3) append t)
+ (4 (font-latex-matched-face 4) append t)
+ (5 (font-latex-matched-face 5) append t)
+ (6 (font-latex-matched-face 6) append t)
+ (7 (font-latex-matched-face 7) append t)))
+ ((eq type 'noarg)
+ `(,(intern (concat prefix name))
+ (0 ,face)))
+ ((eq type 'declaration)
+ `(,(intern (concat prefix name))
+ (0 'font-latex-warning-face t t)
+ (1 'font-lock-keyword-face append t)
+ (2 ,face append t)))))
+
+(defun font-latex-make-built-in-keywords ()
+ "Build defuns, defvars and defcustoms for built-in keyword fontification."
+ (dolist (item font-latex-built-in-keyword-classes)
+ (let ((prefix "font-latex-match-")
+ (name (nth 0 item))
+ (keywords (nth 1 item))
+ (face (nth 2 item))
+ (level (nth 3 item))
+ (type (nth 4 item)))
+
+ ;; defvar font-latex-match-*-keywords-local
+ (eval `(defvar ,(intern (concat prefix name "-keywords-local"))
+ ',keywords
+ ,(concat "Buffer-local keywords to add to `"
+ prefix name "-keywords'.
+This must be a list of keyword strings \(not regular expressions\) omitting
+the leading backslash. It will get transformed into a regexp using
+`" prefix name "-make'. This variable is not for end users; they
+should customize `" prefix name "-keywords' instead. It is for
+authors of Lisp files that get loaded when LaTeX style files are used in the
+current buffer. They should add keywords to this list and rebuild the
+fontification regexp like so:
+
+ (add-to-list '" prefix name "-keywords-local \"setstuff\")
+ (" prefix name "-make)
+
+Generated by `font-latex-make-built-in-keywords'.")))
+ (eval `(make-variable-buffer-local
+ ',(intern (concat prefix name "-keywords-local"))))
+
+ ;; defun font-latex-match-*-make
+ ;; Note: The functions are byte-compiled at the end of font-latex.el.
+ (eval `(defun ,(intern (concat prefix name "-make")) ()
+ ,(concat "Make or remake the variable `" prefix name "'.
+
+Generated by `font-latex-make-built-in-keywords'.")
+ (let ((keywords
+ (append
+ (unless (member ,name
+ font-latex-deactivated-keyword-classes)
+ ,(intern (concat prefix name "-keywords-local")))
+ ,(intern (concat prefix name "-keywords"))))
+ multi-char-macros single-char-macros)
+ (dolist (elt keywords)
+ (let ((keyword (if (listp elt) (car elt) elt)))
+ (if (string-match "^[A-Za-z]" keyword)
+ (add-to-list 'multi-char-macros keyword)
+ (add-to-list 'single-char-macros keyword))))
+ (when (or multi-char-macros single-char-macros)
+ (setq ,(intern (concat prefix name))
+ (concat
+ "\\\\\\("
+ (when multi-char-macros
+ (concat
+ "\\(?:" (regexp-opt multi-char-macros) "\\)\\>"))
+ (when single-char-macros
+ (concat
+ (when multi-char-macros "\\|")
+ "\\(?:" (regexp-opt single-char-macros) "\\)"))
+ "\\)"))))))
+
+ ;; defcustom font-latex-match-*-keywords
+ (eval `(defcustom ,(intern (concat prefix name "-keywords")) nil
+ ,(concat "List of keyword strings for " name " face.
+Each string has to be the name of a macro omitting the leading backslash.
+
+Setting this variable directly does not take effect;
+restart Emacs.
+
+Generated by `font-latex-make-built-in-keywords'.")
+ :type '(repeat (list (string :tag "Keyword")
+ (string :tag "Format")))
+ :set (lambda (symbol value)
+ (set-default symbol value)
+ (funcall ',(intern (concat prefix name "-make"))))
+ :group 'font-latex-keywords))
+
+ ;; defvar font-latex-match-*
+ (eval `(defvar ,(intern (concat prefix name))
+ ,(intern (concat prefix name "-keywords"))))
+ (eval `(make-variable-buffer-local
+ ',(intern (concat prefix name))))
+
+ ;; defun font-latex-match-*
+ (font-latex-make-match-defun prefix name face type)
+
+ ;; Add matchers and highlighters to `font-latex-keywords-{1,2}'.
+ (let ((keywords-entry (font-latex-keyword-matcher
+ prefix name face type)))
+ (add-to-list (intern (concat "font-latex-keywords-"
+ (number-to-string level)))
+ keywords-entry t)
+ (when (= level 1)
+ (add-to-list (intern (concat "font-latex-keywords-2"))
+ keywords-entry t))))))
+(font-latex-make-built-in-keywords)
+
+(defcustom font-latex-user-keyword-classes nil
+ "User-defined keyword classes and specifications for font locking.
+
+When adding new entries, you have to use unique values for the
+class names, i.e. they must not clash with names of the built-in
+keyword classes or other names given by you. Additionally the
+names must not contain spaces.
+
+The keywords are names of commands you want to match omitting the
+leading backslash. In case you want to match LaTeX macros with
+arguments (see below), you should choose the option \"Keywords
+with specs\" which lets you specify the occurence and order of
+optional (\"[]\") and mandatory (\"{}\") arguments for each
+keyword. For example for \"documentclass\" you'd use \"[]{}\"
+because the macro has one optional followed by one mandatory
+argument.
+
+The face argument can either be an existing face or font
+specifications made by you. (The latter option is not available
+on XEmacs.)
+
+There are three alternatives for the type of keywords:
+
+\"Command with arguments\" comprises commands with the syntax
+\"\\foo[bar]{baz}\". The mandatory arguments in curly braces
+will get the face you specified.
+
+\"Declaration inside TeX group\" comprises commands with the
+syntax \"{\\foo bar}\". The content inside the braces, excluding
+the command will get the face you specified. In case the braces
+are missing, the face will be applied to the command itself.
+
+\"Command without arguments\" comprises commands with the syntax
+\"\\foo\". The command itself will get the face you specified.
+
+Setting this variable directly does not take effect;
+use \\[customize] or restart Emacs."
+ :group 'font-latex-keywords
+ :type `(repeat (list (string :tag "Name")
+ (choice (repeat :tag "Keywords" (string :tag "Keyword"))
+ (repeat
+ :tag "Keywords with specs"
+ (group (string :tag "Keyword")
+ (string :tag "Format specifier"))))
+ ,(if (featurep 'xemacs)
+ '(face :tag "Face name")
+ '(choice (custom-face-edit :tag "Face attributes")
+ (face :tag "Face name")))
+ (choice :tag "Type"
+ ;; Maps to
+ ;;`font-latex-match-command-with-arguments'
+ (const :tag "Command with arguments"
+ command)
+ ;; Maps to
+ ;;`font-latex-match-command-in-braces'
+ (const :tag "Declaration inside TeX group"
+ declaration)
+ ;; Maps to `re-search-forward'
+ (const :tag "Command without arguments"
+ noarg))))
+ :set (lambda (symbol value)
+ (dolist (item value)
+ (when (string-match " " (car item))
+ (error "No spaces allowed in name")))
+ (let (names names-uniq)
+ (dolist (item (append font-latex-built-in-keyword-classes value))
+ (setq names (append names (list (car item)))))
+ (setq names (TeX-sort-strings names))
+ (setq names-uniq (TeX-delete-duplicate-strings names))
+ (dotimes (i (safe-length names-uniq))
+ (unless (string= (nth i names) (nth i names-uniq))
+ (error "Name %S already exists" (nth i names)))))
+ (set-default symbol value)
+ (let ((prefix "font-latex-match-"))
+ (dolist (elt value)
+ (unless (boundp (intern (concat prefix (car elt))))
+ ;; defvar font-latex-match-*
+ (eval `(defvar ,(intern (concat prefix (car elt))) nil)))
+ (let ((keywords (nth 1 elt)))
+ (set (intern (concat prefix (car elt)))
+ (when (and (listp keywords)
+ (> (safe-length keywords) 0))
+ (concat "\\\\" (let ((max-specpdl-size 1000))
+ (regexp-opt (if (listp (car keywords))
+ (mapcar 'car keywords)
+ keywords) t))))))))))
+
+(defun font-latex-make-user-keywords ()
+ "Build defuns and defvars for user keyword fontification."
+ (let ((keyword-specs font-latex-user-keyword-classes))
+ (dolist (item keyword-specs)
+ (let ((prefix "font-latex-match-")
+ (name (nth 0 item))
+ (keywords (nth 1 item))
+ (face (nth 2 item))
+ (type (nth 3 item)))
+
+ ;; defvar font-latex-match-*-keywords
+ (eval `(defvar ,(intern (concat prefix name "-keywords")) ',keywords
+ ,(concat "Font-latex keywords for " name " face.
+
+Generated by `font-latex-make-user-keywords'.")))
+
+ ;; defun font-latex-match-*
+ (eval `(font-latex-make-match-defun prefix name '',face type))
+
+ ;; Add the matcher to `font-latex-keywords-2'.
+ (add-to-list 'font-latex-keywords-2
+ (font-latex-keyword-matcher prefix name face type) t))))
+
+ ;; Add the "fixed" matchers and highlighters.
+ (dolist (item
+ '(("\\(^\\|[^\\]\\)\\(&+\\)" 2 'font-latex-warning-face)
+ ("\\$\\$\\([^$]+\\)\\$\\$" 1 'font-latex-math-face)
+ (font-latex-match-quotation
+ (0 'font-latex-string-face append)
+ (1 'font-latex-warning-face))
+ ;; Hack to remove the verbatim face from the \ in
+ ;; \end{verbatim} and similar. The same hack is used in
+ ;; tex-mode.el.
+ ("^[ \t]*\\(\\\\\\)end"
+ (1 (get-text-property (match-end 1) 'face) t))))
+ (add-to-list 'font-latex-keywords-1 item)
+ (add-to-list 'font-latex-keywords-2 item))
+ (dolist (item
+ '((font-latex-match-math-env
+ (0 'font-latex-warning-face t t)
+ (1 'font-latex-math-face append t))
+ (font-latex-match-math-envII
+ (0 'font-latex-math-face append t))
+ (font-latex-match-simple-command
+ (0 'font-latex-sedate-face append))
+ (font-latex-match-script
+ (1 (font-latex-script (match-beginning 0)) append))))
+ (add-to-list 'font-latex-keywords-2 item t)))
+(font-latex-make-user-keywords)
+
+(defvar font-latex-keywords font-latex-keywords-1
+ "Default expressions to highlight in TeX mode.")
+
+
+;;; Subscript and superscript
+
+(defcustom font-latex-fontify-script (not (featurep 'xemacs))
+ "If non-nil, fontify subscript and superscript strings.
+This feature does not work in XEmacs."
+ :type 'boolean
+ :group 'font-latex)
+
+(defcustom font-latex-script-display '((raise -0.3) . (raise 0.3))
+ "Display specification for subscript and superscript content.
+The car is used for subscript, the cdr is used for superscripts."
+ :group 'font-latex
+ :type '(cons (choice (sexp :tag "Subscript form")
+ (const :tag "No lowering" nil))
+ (choice (sexp :tag "Superscript form")
+ (const :tag "No raising" nil))))
+
+
+;;; Syntactic keywords
+
+(defun font-latex-set-syntactic-keywords ()
+ "Set the variable `font-latex-syntactic-keywords'.
+This function can be used to refresh the variable in case other
+variables influencing its value, like `LaTeX-verbatim-environments',
+have changed."
+ ;; Checks for non-emptiness of lists added in order to cater for
+ ;; installations where `(regexp-opt-group nil)' would enter a loop.
+ (let ((verb-envs (and (fboundp 'LaTeX-verbatim-environments)
+ (LaTeX-verbatim-environments)))
+ (verb-macros-with-delims
+ (and (fboundp 'LaTeX-verbatim-macros-with-delims)
+ (LaTeX-verbatim-macros-with-delims)))
+ (verb-macros-with-braces
+ (and (fboundp 'LaTeX-verbatim-macros-with-braces)
+ (LaTeX-verbatim-macros-with-braces))))
+ (setq verb-envs (and verb-envs (regexp-opt verb-envs))
+ verb-macros-with-delims (and verb-macros-with-delims
+ (regexp-opt verb-macros-with-delims))
+ verb-macros-with-braces (and verb-macros-with-braces
+ (regexp-opt verb-macros-with-braces))
+ font-latex-syntactic-keywords nil)
+ (unless (= (length verb-envs) 0)
+ (add-to-list 'font-latex-syntactic-keywords
+ `(,(concat "^[ \t]*\\\\begin *{\\(?:" verb-envs
+ "\\)}.*\\(\n\\)")
+ (1 "|" t)))
+ (add-to-list 'font-latex-syntactic-keywords
+ ;; Using the newline character for the syntax
+ ;; property often resulted in fontification
+ ;; problems when text was inserted at the end of
+ ;; the verbatim environment. That's why we now use
+ ;; the starting backslash of \end. There is a hack
+ ;; in `font-latex-make-user-keywords' to remove the
+ ;; spurious fontification of the backslash.
+ `(,(concat "^[ \t]*\\(\\\\\\)end *{\\(?:" verb-envs "\\)}")
+ (1 "|" t))))
+ (unless (= (length verb-macros-with-delims) 0)
+ (add-to-list 'font-latex-syntactic-keywords
+ `(,(concat "\\\\\\(?:" verb-macros-with-delims "\\)"
+ ;; An opening curly brace as delimiter
+ ;; is valid, but allowing it might screw
+ ;; up fontification of stuff like
+ ;; "\url{...} foo \textbf{<--!...}".
+ "\\(address@hidden).*?"
+ ;; Give an escape char at the end of the
+ ;; verbatim construct punctuation syntax.
+ ;; Prevents wrong fontification of stuff
+ ;; like "\verb|foo\|".
+ "\\(" (regexp-quote TeX-esc) "*\\)\\(\\1\\)")
+ (1 "\"") (2 ".") (3 "\""))))
+ (unless (= (length verb-macros-with-braces) 0)
+ (add-to-list 'font-latex-syntactic-keywords
+ `(,(concat "\\\\\\(?:" verb-macros-with-braces "\\)"
+ "\\({\\).*?[^\\]\\(?:\\\\\\\\\\)*\\(}\\)")
+ (1 "|") (2 "|")))))
+ ;; Cater for docTeX mode.
+ (setq font-latex-doctex-syntactic-keywords
+ (append font-latex-syntactic-keywords
+ ;; For docTeX comment-in-doc.
+ `(("\\(\\^\\)\\^A" (1 (font-latex-doctex-^^A)))))))
+
+(defvar font-latex-syntactic-keywords nil
+ "Syntactic keywords used by `font-latex'.")
+(make-variable-buffer-local 'font-latex-syntactic-keywords)
+
+
+;;; Syntactic fontification
+
+;; Copy and adaptation of `tex-font-lock-syntactic-face-function' in
+;; `tex-mode.el' of CVS Emacs (March 2004)
+(defun font-latex-syntactic-face-function (state)
+ (let ((char (nth 3 state)))
+ (cond
+ ((not char) 'font-lock-comment-face)
+ ((eq char ?$) 'font-latex-math-face)
+ (t
+ (when (char-valid-p char)
+ ;; This is a \verb?...? construct. Let's find the end and mark it.
+ (save-excursion
+ (skip-chars-forward (string ?^ char)) ;; Use `end' ?
+ (when (eq (char-syntax (preceding-char)) ?/)
+ (put-text-property (1- (point)) (point) 'syntax-table '(1)))
+ (unless (eobp)
+ (put-text-property (point) (1+ (point)) 'syntax-table '(7)))))
+ 'font-latex-verbatim-face))))
+
+
+;;; Faces
+
+(defface font-latex-bold-face
+ (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit bold))
+ ((assq :weight custom-face-attributes) '(:weight bold))
+ (t '(:bold t)))))
+ `((((class grayscale) (background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale) (background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color) (background light))
+ (:foreground "DarkOliveGreen" ,@font))
+ (((class color) (background dark))
+ (:foreground "OliveDrab" ,@font))
+ (t (,@font))))
+ "Face used to highlight text to be typeset in bold."
+ :group 'font-latex-highlighting-faces)
+
+(defface font-latex-italic-face
+ (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit italic))
+ ((assq :slant custom-face-attributes) '(:slant italic))
+ (t '(:italic t)))))
+ `((((class grayscale) (background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale) (background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color) (background light))
+ (:foreground "DarkOliveGreen" ,@font))
+ (((class color) (background dark))
+ (:foreground "OliveDrab" ,@font))
+ (t (,@font))))
+ "Face used to highlight text to be typeset in italic."
+ :group 'font-latex-highlighting-faces)
+
+(defface font-latex-math-face
+ (let ((font (cond ((assq :inherit custom-face-attributes)
+ '(:inherit underline))
+ (t '(:underline t)))))
+ `((((class grayscale) (background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale) (background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color) (background light))
+ (:foreground "SaddleBrown"))
+ (((class color) (background dark))
+ (:foreground "burlywood"))
+ (t (,@font))))
+ "Face used to highlight math."
+ :group 'font-latex-highlighting-faces)
+
+(defface font-latex-sedate-face
+ '((((class grayscale) (background light)) (:foreground "DimGray"))
+ (((class grayscale) (background dark)) (:foreground "LightGray"))
+ (((class color) (background light)) (:foreground "DimGray"))
+ (((class color) (background dark)) (:foreground "LightGray"))
+ ;;;(t (:underline t))
+ )
+ "Face used to highlight sedate stuff."
+ :group 'font-latex-highlighting-faces)
+
+(defface font-latex-string-face
+ (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit italic))
+ ((assq :slant custom-face-attributes) '(:slant italic))
+ (t '(:italic t)))))
+ `((((type tty) (class color))
+ (:foreground "green"))
+ (((class grayscale) (background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale) (background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color) (background light))
+ (:foreground "RosyBrown"))
+ (((class color) (background dark))
+ (:foreground "LightSalmon"))
+ (t (,@font))))
+ "Face used to highlight strings."
+ :group 'font-latex-highlighting-faces)
+
+(defface font-latex-warning-face
+ (let ((font (cond ((assq :inherit custom-face-attributes) '(:inherit bold))
+ ((assq :weight custom-face-attributes) '(:weight bold))
+ (t '(:bold t)))))
+ `((((class grayscale)(background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale)(background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color)(background light))
+ (:foreground "red" ,@font))
+ (((class color)(background dark))
+ (:foreground "red" ,@font))
+ (t (,@font))))
+ "Face for important keywords."
+ :group 'font-latex-highlighting-faces)
+
+(defface font-latex-verbatim-face
+ (let ((font (if (and (assq :inherit custom-face-attributes)
+ (if (featurep 'xemacs)
+ (find-face 'fixed-pitch)
+ (facep 'fixed-pitch)))
+ '(:inherit fixed-pitch)
+ '(:family "courier"))))
+ `((((class grayscale) (background light))
+ (:foreground "DimGray" ,@font))
+ (((class grayscale) (background dark))
+ (:foreground "LightGray" ,@font))
+ (((class color) (background light))
+ (:foreground "SaddleBrown" ,@font))
+ (((class color) (background dark))
+ (:foreground "burlywood" ,@font))
+ (t (,@font))))
+ "Face used to highlight TeX verbatim environments."
+ :group 'font-latex-highlighting-faces)
+
+(defface font-latex-superscript-face
+ '((t (:height 0.8)))
+ "Face used for superscripts."
+ :group 'font-latex-highlighting-faces)
+
+(defface font-latex-subscript-face
+ '((t (:height 0.8)))
+ "Face used for subscripts."
+ :group 'font-latex-highlighting-faces)
+
+(defface font-latex-slide-title-face
+ (let* ((scale 1.2)
+ (size (when (featurep 'xemacs)
+ (round (* 0.9 (face-height 'default) scale)))))
+ (if (featurep 'xemacs)
+ `((t (:bold t :family "helvetica" :size ,size)))
+ `((t (:inherit (variable-pitch font-lock-type-face)
+ :weight bold :height ,scale)))))
+ "Face for slide titles."
+ :group 'font-latex-highlighting-faces)
+(when (featurep 'xemacs)
+ (set-face-parent 'font-latex-slide-title-face 'font-lock-type-face
+ nil nil 'append))
+
+
+;;; Setup
+
+(defvar font-lock-comment-start-regexp nil
+ "Regexp to match the start of a comment.")
+
+(defvar font-latex-extend-region-functions nil
+ "List of functions extending the region for multiline constructs.
+
+Each function should accept two arguments, the begin and end of
+the region to be fontified, and return the new region start. If
+no extension is necessary, the original region start should be
+returned.
+
+All specified functions will be called and the region extended
+backwards to the minimum over their return values.")
+
+;;;###autoload
+(defun font-latex-setup ()
+ "Setup this buffer for LaTeX font-lock. Usually called from a hook."
+ (font-latex-set-syntactic-keywords)
+ ;; Trickery to make $$ fontification be in `font-latex-math-face' while
+ ;; strings get whatever `font-lock-string-face' has been set to.
+ (when (fboundp 'built-in-face-specifiers)
+ ;; Cool patch from Christoph Wedler...
+ (let (instance)
+ (mapcar (lambda (property)
+ (setq instance
+ (face-property-instance 'font-latex-math-face property
+ nil 0 t))
+ (if (numberp instance)
+ (setq instance
+ (face-property-instance 'default property nil 0)))
+ (or (numberp instance)
+ (set-face-property 'font-lock-string-face property
+ instance (current-buffer))))
+ (built-in-face-specifiers))))
+
+ ;; Configure multi-line fontification.
+ (when (and font-latex-do-multi-line
+ (boundp 'font-lock-multiline))
+ (set (make-local-variable 'font-lock-multiline) t))
+
+ ;; Functions for extending the region.
+ (dolist (elt '(font-latex-extend-region-backwards-command-with-args
+ font-latex-extend-region-backwards-command-in-braces
+ font-latex-extend-region-backwards-quotation
+ font-latex-extend-region-backwards-math-env
+ font-latex-extend-region-backwards-math-envII))
+ (add-to-list 'font-latex-extend-region-functions elt))
+
+ ;; Tell Font Lock about the support.
+ (make-local-variable 'font-lock-defaults)
+ ;; The test for `major-mode' currently only works with docTeX mode
+ ;; because `TeX-install-font-lock' is called explicitely in
+ ;; `doctex-mode'. In case other modes have to be distinguished as
+ ;; well, remove the call to `TeX-install-font-lock' from
+ ;; `VirTeX-common-initialization' and place it in the different
+ ;; `xxx-mode' calls instead, but _after_ `major-mode' is set.
+ (cond
+ ((eq major-mode 'doctex-mode)
+ (setq font-lock-defaults
+ '((font-latex-keywords font-latex-keywords-1 font-latex-keywords-2
+ font-latex-doctex-keywords)
+ nil nil ((?\( . ".") (?\) . ".") (?$ . "\"")) nil
+ (font-lock-comment-start-regexp . "%")
+ (font-lock-mark-block-function . mark-paragraph)
+ (font-lock-fontify-region-function
+ . font-latex-fontify-region)
+ (font-lock-unfontify-region-function
+ . font-latex-unfontify-region)
+ (font-lock-syntactic-face-function
+ . font-latex-doctex-syntactic-face-function)
+ (font-lock-syntactic-keywords
+ . font-latex-doctex-syntactic-keywords))))
+ (t
+ (setq font-lock-defaults
+ '((font-latex-keywords font-latex-keywords-1 font-latex-keywords-2)
+ nil nil ((?\( . ".") (?\) . ".") (?$ . "\"")) nil
+ (font-lock-comment-start-regexp . "%")
+ (font-lock-mark-block-function . mark-paragraph)
+ (font-lock-fontify-region-function
+ . font-latex-fontify-region)
+ (font-lock-unfontify-region-function
+ . font-latex-unfontify-region)
+ (font-lock-syntactic-face-function
+ . font-latex-syntactic-face-function)
+ (font-lock-syntactic-keywords
+ . font-latex-syntactic-keywords))))))
+
+(defun font-latex-fontify-region (beg end &optional loudly)
+ "Fontify region from BEG to END.
+If optional argument is non-nil, print status messages."
+ (setq beg (apply 'min (mapcar (lambda (fun) (funcall fun beg end))
+ font-latex-extend-region-functions)))
+ ;; Stolen from `jit-lock-after-change'. Without this stanza only
+ ;; the line in which a change happened will be refontified. The
+ ;; rest to which the region was extended will only be refontified
+ ;; upon redisplay. Unfortunately refontification is not done as
+ ;; fast as if `jit-lock-after-change' was advised.
+ (when (and (boundp 'jit-lock-context-unfontify-pos)
+ jit-lock-context-unfontify-pos)
+ (setq jit-lock-context-unfontify-pos
+ (min jit-lock-context-unfontify-pos beg)))
+ (font-lock-default-fontify-region beg end loudly))
+
+;; Copy and adaption of `tex-font-lock-unfontify-region' from
+;; tex-mode.el in GNU Emacs on 2004-08-04.
+(defun font-latex-unfontify-region (beg end)
+ "Unfontify region from BEG to END."
+ (font-lock-default-unfontify-region beg end)
+ (while (< beg end)
+ (let ((next (next-single-property-change beg 'display nil end))
+ (prop (get-text-property beg 'display)))
+ (if (and (eq (car-safe prop) 'raise)
+ (member (car-safe (cdr prop))
+ (list (nth 1 (car font-latex-script-display))
+ (nth 1 (cdr font-latex-script-display))))
+ (null (cddr prop)))
+ (put-text-property beg next 'display nil))
+ (setq beg next))))
+
+
+;;; Utility functions
+
+(defun font-latex-find-matching-close (openchar closechar)
+ "Skip over matching pairs of OPENCHAR and CLOSECHAR.
+OPENCHAR is the opening character and CLOSECHAR is the closing
+character. Character pairs are usually { } or [ ]. Comments are
+ignored during the search."
+ (let ((parse-sexp-ignore-comments
+ (not (eq major-mode 'doctex-mode))) ; scan-sexps ignores comments
+ (init-point (point))
+ (mycount 1)
+ (esc-char (or (and (boundp 'TeX-esc) TeX-esc) "\\")))
+ (or
+ (condition-case nil
+ (progn
+ (goto-char (with-syntax-table
+ (let ((table (TeX-search-syntax-table)))
+ ;; Give `openchar' and `closechar' open paren and
+ ;; close paren syntax respectively.
+ (modify-syntax-entry
+ openchar (concat "(" (char-to-string closechar))
+ table)
+ (modify-syntax-entry
+ closechar (concat ")" (char-to-string openchar))
+ table)
+ table)
+ (scan-sexps (point) 1)))
+ ;; No error code. See if closechar is unquoted
+ (save-excursion
+ (backward-char 1)
+ (zerop (mod (skip-chars-backward (regexp-quote esc-char)) 2))))
+ (error nil))
+ (save-match-data
+ (goto-char (1+ init-point))
+ (while (and (> mycount 0)
+ (re-search-forward
+ (string ?\[
+ ;; closechar might be ]
+ ;; and therefor must be first in regexp
+ closechar openchar
+ ?\])
+ nil t))
+ (cond
+ ((font-latex-commented-outp)
+ (forward-line 1))
+ ((save-excursion
+ (backward-char 1)
+ (zerop (mod (skip-chars-backward (regexp-quote esc-char))
+ 2)))
+ (setq mycount (+ mycount
+ (if (= (preceding-char) openchar) 1 -1)))))))
+ (if (= mycount 0)
+ t
+ (goto-char init-point)
+ nil))))
+
+(defun font-latex-commented-outp ()
+ "Return t if comment character is found between bol and point."
+ (save-excursion
+ (let ((limit (point))
+ (esc-char (if (and (boundp 'TeX-esc) TeX-esc) TeX-esc "\\")))
+ (forward-line 0)
+ (if (and (eq (char-after) ?\%)
+ (not (font-latex-faces-present-p 'font-latex-verbatim-face)))
+ (not (eq major-mode 'doctex-mode))
+ (catch 'found
+ (while (progn (skip-chars-forward "^%" limit)
+ (< (point) limit))
+ (when (and (save-excursion
+ (zerop (mod (skip-chars-backward
+ (regexp-quote esc-char)) 2)))
+ (not (font-latex-faces-present-p
+ 'font-latex-verbatim-face)))
+ (throw 'found t))
+ (forward-char)))))))
+
+(defun font-latex-faces-present-p (faces &optional pos)
+ "Return t if FACES are present at position POS.
+FACES may be a single face or a list of faces.
+If POS is omitted, the current position of point is used."
+ (let* ((faces (if (listp faces) faces (list faces)))
+ (pos (or pos (point)))
+ (prop (get-text-property pos 'face))
+ (prop-list (if (listp prop) prop (list prop))))
+ (catch 'member
+ (dolist (item prop-list)
+ (when (memq item faces)
+ (throw 'member t))))))
+
+(defun font-latex-forward-comment ()
+ "Like `forward-comment' but with special provisions for docTeX mode.
+In docTeX mode \"%\" at the start of a line will be treated as whitespace."
+ (if (eq major-mode 'doctex-mode)
+ ;; XXX: We should probably cater for ^^A as well.
+ (progn
+ (while (progn (if (bolp) (skip-chars-forward "%"))
+ (> (skip-chars-forward " \t\n") 0)))
+ (when (eq (char-after) ?%)
+ (beginning-of-line 2)
+ t))
+ (forward-comment 1)))
+
+
+;;; Match functions
+
+(defvar font-latex-matched-faces nil)
+
+(defun font-latex-matched-face (pos)
+ (nth pos font-latex-matched-faces))
+
+(defun font-latex-match-command-with-arguments (regexp keywords face limit)
+ "Search for regexp command KEYWORDS[opt]{arg} before LIMIT.
+Returns nil if none of KEYWORDS is found."
+ (setq font-latex-matched-faces nil)
+ (catch 'match
+ (while (re-search-forward regexp limit t)
+ (unless (font-latex-faces-present-p '(font-lock-comment-face
+ font-latex-verbatim-face)
+ (match-beginning 0))
+ (let ((beg (match-beginning 0))
+ match-data
+ (spec (cadr (assoc (match-string 1) keywords)))
+ (parse-sexp-ignore-comments t)) ; scan-sexps ignores comments
+ (add-to-list 'match-data beg)
+ (goto-char (match-end 0))
+ (when (and (> (length spec) 0)
+ (string= (substring spec 0 1) "*"))
+ (setq spec (substring spec 1))
+ (skip-chars-forward "*" (1+ (point))))
+ (add-to-list 'match-data (point) t)
+ (add-to-list 'font-latex-matched-faces 'font-lock-keyword-face)
+ (while (and (not (eobp)) (font-latex-forward-comment)))
+ (catch 'break
+ (while (> (length spec) 0)
+ (let ((opening-tag (string-to-char (substring spec 0 1)))
+ (closing-tag (string-to-char (substring spec 1 2)))
+ match-beg)
+ (setq spec (substring spec 2))
+ (if (eq opening-tag ?\{)
+ ;; Mandatory arguments {...}
+ (if (eq (following-char) opening-tag)
+ (progn
+ (setq match-beg (point))
+ (if (font-latex-find-matching-close opening-tag
+ closing-tag)
+ (progn
+ (nconc match-data (list (1+ match-beg)
+ (1- (point))))
+ (nconc font-latex-matched-faces (list face)))
+ (nconc match-data (list match-beg (1+ match-beg)))
+ (nconc font-latex-matched-faces
+ (list 'font-latex-warning-face))
+ (throw 'break nil)))
+ ;; Add the warning face at the front of the list because
+ ;; the matcher uses 'append and the face would otherwise
+ ;; be overridden by the keyword face. (Alternatively
+ ;; the start of the keyword face could be adjusted.)
+ (setq match-data (append (list beg (1+ beg)) match-data))
+ (push 'font-latex-warning-face font-latex-matched-faces))
+ ;; Optional arguments [...] and others
+ (when (eq (following-char) opening-tag)
+ (setq match-beg (point))
+ (if (font-latex-find-matching-close opening-tag closing-tag)
+ (progn
+ (nconc match-data (list (1+ match-beg) (1- (point))))
+ (nconc font-latex-matched-faces
+ (list 'font-lock-variable-name-face)))
+ (nconc match-data (list match-beg (1+ match-beg)))
+ (nconc font-latex-matched-faces
+ (list 'font-latex-warning-face))
+ (throw 'break nil))
+ (while (and (not (eobp)) (font-latex-forward-comment))))))))
+ (store-match-data match-data)
+ (throw 'match t))))))
+
+(defun font-latex-extend-region-backwards-command-with-args (beg end)
+ "Extend region backwards if necessary for a multiline construct to fit in."
+ (save-excursion
+ (goto-char end)
+ (catch 'extend
+ (while (TeX-search-backward-unescaped "}" beg t)
+ (let ((macro-start (TeX-find-macro-start
+ (max (point-min)
+ (- beg font-latex-multiline-boundary)))))
+ (when (and macro-start
+ (< macro-start beg))
+ (throw 'extend macro-start))))
+ beg)))
+
+;; XXX: Check if `font-latex-multiline-boundary' has to be taken into account.
+(defun font-latex-match-command-in-braces (keywords limit)
+ "Search for command like {\\bfseries fubar} before LIMIT.
+Sets `match-data' so that:
+ subexpression 0 is a warning indicator,
+ subexpression 1 is the keyword, and
+ subexpression 2 is the rest in the TeX group.
+Returns nil if no command is found."
+ (catch 'match
+ (while (re-search-forward keywords limit t)
+ (unless (font-latex-faces-present-p '(font-lock-comment-face
+ font-latex-verbatim-face)
+ (match-beginning 0))
+ (let ((kbeg (match-beginning 0)) (kend (match-end 1))
+ (beg (match-end 0))
+ end cbeg cend
+ (parse-sexp-ignore-comments t)) ; scan-sexps ignores comments
+ (goto-char kbeg)
+ (if (not (eq (preceding-char) ?\{))
+ ;; Fontify only the keyword (no argument found).
+ (progn
+ (setq cbeg kbeg cend kend)
+ (goto-char (match-end 0))
+ (store-match-data (list (point) (point)
+ (point) (point)
+ cbeg cend))
+ (throw 'match t))
+ ;; There's an opening bracket
+ (save-restriction
+ ;; Restrict to LIMIT.
+ (narrow-to-region (point-min) limit)
+ (forward-char -1) ; Move on the opening bracket
+ (if (font-latex-find-matching-close ?\{ ?\})
+ (store-match-data (list kbeg kbeg
+ kbeg kend
+ beg (1- (point))))
+ (goto-char kend)
+ (store-match-data (list (1- kbeg) kbeg
+ kbeg kend
+ kend kend)))
+ (throw 'match t))))))))
+
+(defun font-latex-extend-region-backwards-command-in-braces (beg end)
+ "Extend region backwards if necessary for a multiline construct to fit in."
+ (save-excursion
+ (goto-char end)
+ (catch 'extend
+ (while (TeX-search-backward-unescaped "}" beg t)
+ (let ((group-start (TeX-find-opening-brace
+ nil (max (point-min)
+ (- beg font-latex-multiline-boundary)))))
+ (when group-start
+ ;; XXX: Actually we'd have to check if any of the
+ ;; declaration-type macros can be found right after the
+ ;; brace. If we don't do this (like now) large regions
+ ;; may be refontified for no good reason. For checking
+ ;; the built-in `font-latex-match-*' variables for
+ ;; declaration-type macros as well as the respective
+ ;; user-defined variables could be concatenated.
+ (goto-char group-start)
+ (when (< group-start beg)
+ (throw 'extend group-start)))))
+ beg)))
+
+(defun font-latex-match-simple-command (limit)
+ "Search for command like \\foo before LIMIT."
+ (TeX-re-search-forward-unescaped "address@hidden" limit t))
+
+(defun font-latex-match-math-env (limit)
+ "Match math pattern up to LIMIT.
+Used for patterns like:
+\\( F = ma \\)
+\\[ F = ma \\] but not \\\\ [len]"
+ (catch 'match
+ (while (re-search-forward "\\(\\\\(\\)\\|\\(\\\\\\[\\)" limit t)
+ (goto-char (match-beginning 0))
+ (if (eq (preceding-char) ?\\) ; \\[ is not a math environment
+ (goto-char (match-end 0))
+ (let ((beg (point)))
+ (if (search-forward (if (match-beginning 1) "\\)" "\\]") limit 'move)
+ (store-match-data (list beg beg beg (point)))
+ (goto-char (+ beg 2))
+ (store-match-data (list beg (point) (point) (point))))
+ (throw 'match t))))))
+
+(defun font-latex-extend-region-backwards-math-env (beg end)
+ "Extend region backwards if necessary for a multiline construct to fit in."
+ (save-excursion
+ (goto-char end)
+ (catch 'extend
+ (while (re-search-backward "\\(\\\\)\\)\\|\\(\\\\]\\)" beg t)
+ (when (and (search-backward (if (match-beginning 1) "\\(" "\\[")
+ (- beg font-latex-multiline-boundary) t)
+ (< (point) beg))
+ (throw 'extend (point))))
+ beg)))
+
+(defcustom font-latex-math-environments
+ '("display" "displaymath" "equation" "eqnarray" "gather" "multline"
+ "align" "alignat" "xalignat")
+ "List of math environment names for font locking."
+ :type '(repeat string)
+ :group 'font-latex)
+
+(defun font-latex-match-math-envII (limit)
+ "Match math patterns up to LIMIT.
+Used for patterns like:
+\\begin{equation}
+ fontified stuff
+\\end{equation}
+The \\begin{equation} and \\end{equation} are not fontified here."
+ (when (re-search-forward (concat "\\\\begin[ \t]*{"
+ (regexp-opt font-latex-math-environments t)
+ "\\*?}")
+ limit t)
+ (let ((beg (match-end 0)) end)
+ (if (re-search-forward (concat "\\\\end[ \t]*{"
+ (buffer-substring-no-properties
+ (match-beginning 1)
+ (match-end 0)))
+ ;; XXX: Should this rather be done by
+ ;; extending the region to be fontified?
+ (+ limit font-latex-multiline-boundary) 'move)
+ (setq end (match-beginning 0))
+ (goto-char beg)
+ (setq end beg))
+ (store-match-data (list beg end))
+ t)))
+
+(defun font-latex-extend-region-backwards-math-envII (beg end)
+ "Extend region backwards if necessary for multiline math environments."
+ (save-excursion
+ (goto-char end)
+ (catch 'extend
+ (while (re-search-backward
+ (concat "\\\\end[ \t]*{"
+ (regexp-opt font-latex-math-environments t)
+ "\\*?}") beg t)
+ (when (and (re-search-backward (concat "\\\\begin[ \t]*{"
+ (buffer-substring-no-properties
+ (match-beginning 1)
+ (match-end 0)))
+ (- beg font-latex-multiline-boundary) t)
+ (< (point) beg))
+ (throw 'extend (point))))
+ beg)))
+
+(defun font-latex-update-quote-list ()
+ "Update quote list and regexp if value of `font-latex-quotes' changed."
+ (unless (eq font-latex-quotes-control font-latex-quotes)
+ (setq font-latex-quotes-control font-latex-quotes)
+ ;; Set order of each entry in `font-latex-quote-list' according to
+ ;; setting of `font-latex-quotes'.
+ (let ((tail font-latex-quote-list)
+ elt)
+ (while tail
+ (setq elt (car tail))
+ (when (and (> (safe-length elt) 2)
+ (not (eq (nth 2 elt) font-latex-quotes)))
+ (setcar tail (list (nth 1 elt) (nth 0 elt) font-latex-quotes)))
+ (setq tail (cdr tail))))
+ (setq font-latex-quote-regexp-beg
+ (regexp-opt (mapcar 'car font-latex-quote-list) t))))
+
+(defun font-latex-match-quotation (limit)
+ "Match quote patterns up to LIMIT.
+Used for patterns like:
+``this is a normal quote'' and these are multilingual quoted strings:
+\"< french \"> and \"`german\"' quotes.
+The quotes << french >> and 8-bit french are used if `font-latex-quotes' is
+set to french, and >>german<< (and 8-bit) are used if set to german."
+ (font-latex-update-quote-list)
+ ;; Search for matches.
+ (catch 'match
+ (while (re-search-forward font-latex-quote-regexp-beg limit t)
+ (unless (font-latex-faces-present-p '(font-lock-comment-face
+ font-latex-verbatim-face)
+ (match-beginning 0))
+ (let* ((beg (match-beginning 0))
+ (after-beg (match-end 0))
+ (opening-quote (match-string 0))
+ (closing-quote
+ (nth 1 (assoc (if (fboundp 'string-make-multibyte)
+ (string-make-multibyte (match-string 0))
+ (match-string 0))
+ font-latex-quote-list)))
+ (nest-count 0)
+ (point-of-surrender (+ beg font-latex-multiline-boundary)))
+ ;; Find closing quote taking nested quotes into account.
+ (while (progn
+ (re-search-forward (concat opening-quote "\\|" closing-quote)
+ point-of-surrender 'move)
+ (when (and (< (point) point-of-surrender) (not (eobp)))
+ (if (string= (match-string 0) opening-quote)
+ (setq nest-count (1+ nest-count))
+ (when (/= nest-count 0)
+ (setq nest-count (1- nest-count)))))))
+ ;; If no closing quote was found, set the second match which
+ ;; will be marked with warning color, if one was found, set
+ ;; the first match which will be marked with string color.
+ (if (or (= (point) point-of-surrender) (eobp))
+ (progn
+ (goto-char after-beg)
+ (store-match-data (list after-beg after-beg beg after-beg)))
+ (store-match-data (list beg (point) (point) (point))))
+ (throw 'match t))))))
+
+(defun font-latex-extend-region-backwards-quotation (beg end)
+ "Extend region backwards if necessary for a multiline construct to fit in."
+ (font-latex-update-quote-list)
+ (let ((regexp-end (regexp-opt (mapcar 'cadr font-latex-quote-list) t)))
+ (save-excursion
+ (goto-char end)
+ (catch 'extend
+ (while (re-search-backward regexp-end beg t)
+ (let ((closing-quote (match-string 0))
+ (nest-count 0)
+ (point-of-surrender (- beg font-latex-multiline-boundary))
+ opening-quote)
+ (catch 'found
+ (dolist (elt font-latex-quote-list)
+ (when (string= (cadr elt) closing-quote)
+ (setq opening-quote (car elt))
+ (throw 'found nil))))
+ ;; Find opening quote taking nested quotes into account.
+ (while (progn
+ (re-search-backward (concat opening-quote "\\|"
+ closing-quote)
+ point-of-surrender 'move)
+ (when (and (> (point) point-of-surrender) (not (bobp)))
+ (if (string= (match-string 0) closing-quote)
+ (setq nest-count (1+ nest-count))
+ (when (/= nest-count 0)
+ (setq nest-count (1- nest-count)))))))
+ (when (< (point) beg)
+ (throw 'extend (point)))))
+ beg))))
+
+;; (defadvice jit-lock-after-change (before TeX-jit-lock-after-change
+;; activate)
+;; "Extend region backwards for multiline constructs."
+;; (let* ((obeg (ad-get-arg 0)))
+;; (ad-set-arg 0 (or (font-latex-extend-region-backwards-quotation
+;; obeg (ad-get-arg 1))
+;; obeg))))
+
+(defun font-latex-match-script (limit)
+ "Match subscript and superscript patterns up to LIMIT."
+ (when font-latex-fontify-script
+ (re-search-forward
+ (eval-when-compile
+ ;; Regexp taken from `tex-font-lock-keywords-3' from
+ ;; tex-mode.el in GNU Emacs on 2004-07-07.
+ (concat "[_^] *\\([^\n\\{}]\\|" "\\\\"
+ "\\(address@hidden|[^ \t\n]\\)" "\\|"
+ "{\\(?:[^{}\\]\\|\\\\.\\|{[^}]*}\\)*" "}\\)"))
+ limit t)))
+
+;; Copy and adaption of `tex-font-lock-suscript' from tex-mode.el in
+;; GNU Emacs on 2004-07-07.
+(defun font-latex-script (pos)
+ "Return face and display spec for subscript and superscript content."
+ (when (and (font-latex-faces-present-p 'font-latex-math-face pos)
+ (not (font-latex-faces-present-p '(font-lock-constant-face
+ font-lock-builtin-face
+ font-lock-comment-face
+ font-latex-verbatim-face) pos))
+ ;; Check for backslash quoting
+ (not (let ((odd nil)
+ (pos pos))
+ (while (eq (char-before pos) ?\\)
+ (setq pos (1- pos) odd (not odd)))
+ odd)))
+ ;; Adding other text properties than `face' is supported by
+ ;; `font-lock-apply-highlight' in CVS Emacsen since 2001-10-28.
+ ;; With the introduction of this feature the variable
+ ;; `font-lock-extra-managed-props' was introduced and serves here
+ ;; for feature checking. XEmacs (CVS and 21.4.15) currently
+ ;; (2004-08-18) does not support this feature.
+ (let ((extra-props-flag (boundp 'font-lock-extra-managed-props)))
+ (if (eq (char-after pos) ?_)
+ (if extra-props-flag
+ `(face font-latex-subscript-face display
+ ,(car font-latex-script-display))
+ 'font-latex-subscript-face)
+ (if extra-props-flag
+ `(face font-latex-superscript-face display
+ ,(cdr font-latex-script-display))
+ 'font-latex-superscript-face)))))
+
+
+;;; docTeX
+
+(defvar font-latex-doctex-preprocessor-face
+ 'font-latex-doctex-preprocessor-face
+ "Face used to highlight preprocessor directives in docTeX mode.")
+
+(defface font-latex-doctex-preprocessor-face
+ '((t (:inherit (font-latex-doctex-documentation-face
+ font-lock-preprocessor-face))))
+ "Face used to highlight preprocessor directives in docTeX mode."
+ :group 'font-latex-highlighting-faces)
+
+(defvar font-latex-doctex-documentation-face
+ 'font-latex-doctex-documentation-face
+ "Face used to highlight the documentation in docTeX mode.")
+
+(defface font-latex-doctex-documentation-face
+ '((((class mono)) (:inverse-video t))
+ (((class grayscale) (background dark)) (:background "#333"))
+ (((class color) (background dark)) (:background "#333"))
+ (t (:background "#eeeeee")))
+ "Face used to highlight the documentation parts in docTeX mode."
+ :group 'font-latex-highlighting-faces)
+
+(defvar font-latex-doctex-keywords
+ (append font-latex-keywords-2
+ '(("^%<[^>]*>" (0 font-latex-doctex-preprocessor-face t)))))
+
+;; Set and updated in `font-latex-set-syntactic-keywords'.
+(defvar font-latex-doctex-syntactic-keywords nil)
+
+;; Copy and adaptation of `doctex-font-lock-^^A' in `tex-mode.el' of
+;; CVS Emacs (March 2004)
+(defun font-latex-doctex-^^A ()
+ (if (eq (char-after (line-beginning-position)) ?\%)
+ (progn
+ (put-text-property
+ (1- (match-beginning 1)) (match-beginning 1) 'syntax-table
+ (if (= (1+ (line-beginning-position)) (match-beginning 1))
+ ;; The `%' is a single-char comment, which Emacs
+ ;; syntax-table can't deal with. We could turn it
+ ;; into a non-comment, or use `\n%' or `%^' as the comment.
+ ;; Instead, we include it in the ^^A comment.
+ ;; COMPATIBILITY for Emacs 20 and XEmacs
+ (eval-when-compile (if (fboundp 'string-to-syntax)
+ (string-to-syntax "< b")
+ '(2097163)))
+ ;; COMPATIBILITY for Emacs 20 and XEmacs
+ (eval-when-compile (if (fboundp 'string-to-syntax)
+ (string-to-syntax ">")
+ '(12)))))
+ (let ((end (line-end-position)))
+ (if (< end (point-max))
+ (put-text-property end (1+ end) 'syntax-table
+ ;; COMPATIBILITY for Emacs 20 and XEmacs
+ (eval-when-compile
+ (if (fboundp 'string-to-syntax)
+ (string-to-syntax "> b")
+ '(2097164))))))
+ ;; COMPATIBILITY for Emacs 20 and XEmacs
+ (eval-when-compile (if (fboundp 'string-to-syntax)
+ (string-to-syntax "< b")
+ '(2097163))))))
+
+;; Copy and adaptation of `doctex-font-lock-syntactic-face-function'
+;; in `tex-mode.el' of CVS Emacs (March 2004)
+(defun font-latex-doctex-syntactic-face-function (state)
+ ;; Mark docTeX documentation, which is parsed as a style A comment
+ ;; starting in column 0.
+ (if (or (nth 3 state) (nth 7 state)
+ (not (memq (char-before (nth 8 state))
+ '(?\n nil))))
+ ;; Anything else is just as for LaTeX.
+ (font-latex-syntactic-face-function state)
+ font-latex-doctex-documentation-face))
+
+
+;;; Installation in non-AUCTeX LaTeX mode
+
+(add-hook 'latex-mode-hook 'font-latex-setup)
+;; If font-latex is loaded using a latex-mode-hook, then the add-hook above
+;; won't be called this time around. Check for this now:
+(if (eq major-mode 'latex-mode)
+ (font-latex-setup))
+
+
+;;; Byte-compilation of generated functions
+
+(when (byte-code-function-p
+ (symbol-function 'font-latex-make-built-in-keywords))
+ (dolist (elt font-latex-built-in-keyword-classes)
+ (let ((name (nth 0 elt)))
+ (byte-compile (intern (concat "font-latex-" name)))
+ (byte-compile (intern (concat "font-latex-" name "-make"))))))
+
+
+;; Provide ourselves:
+(provide 'font-latex)
+
+;; Local Variables:
+;; coding: iso-8859-1
+;; End:
+
+;;; font-latex.el ends here
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [AUCTeX-diffs] Changes to auctex/font-latex.el [multiline-font-lock],
Ralf Angeli <=