]> code.delx.au - gnu-emacs/blobdiff - lisp/font-lock.el
Fix last change to custom-push-theme.
[gnu-emacs] / lisp / font-lock.el
index ba42412d8da3e1c5d02870738cd9f7920d8df6be..4c43d34dde7f483c5f4bc5e7db07a791dab70b0d 100644 (file)
@@ -1,7 +1,7 @@
 ;;; font-lock.el --- Electric font lock mode
 
 ;; Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-;;   2000, 2001, 2002, 2003, 2004 2005  Free Software Foundation, Inc.
+;;   2000, 2001, 2002, 2003, 2004 2005 Free Software Foundation, Inc.
 
 ;; Author: jwz, then rms, then sm
 ;; Maintainer: FSF
@@ -21,8 +21,8 @@
 
 ;; 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.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 (defgroup font-lock-extra-types nil
   "Extra mode-specific type names for highlighting declarations."
   :group 'font-lock)
-
-;; Define support mode groups here to impose `font-lock' group order.
-(defgroup fast-lock nil
-  "Font Lock support mode to cache fontification."
-  :load 'fast-lock
-  :group 'font-lock)
-
-(defgroup lazy-lock nil
-  "Font Lock support mode to fontify lazily."
-  :load 'lazy-lock
-  :group 'font-lock)
 \f
 ;; User variables.
 
@@ -293,7 +282,7 @@ If a number, only buffers greater than this size have fontification messages."
                 (integer :tag "size"))
   :group 'font-lock)
 
-(defcustom font-lock-lines-before 1
+(defcustom font-lock-lines-before 0
   "*Number of lines before the changed text to include in refontification."
   :type 'integer
   :group 'font-lock
@@ -430,7 +419,7 @@ where MATCHER is a regexp to search for or the function name to call to make
 the search, as for MATCH-HIGHLIGHT above, but with one exception; see below.
 PRE-MATCH-FORM and POST-MATCH-FORM are evaluated before the first, and after
 the last, instance MATCH-ANCHORED's MATCHER is used.  Therefore they can be
-used to initialise before, and cleanup after, MATCHER is used.  Typically,
+used to initialize before, and cleanup after, MATCHER is used.  Typically,
 PRE-MATCH-FORM is used to move to some position relative to the original
 MATCHER, before starting with MATCH-ANCHORED's MATCHER.  POST-MATCH-FORM might
 be used to move back, before resuming with MATCH-ANCHORED's parent's MATCHER.
@@ -563,11 +552,11 @@ is not in a string or comment and not within any bracket-pairs (or else,
 a place such that any bracket-pairs outside it can be ignored for Emacs
 syntax analysis and fontification).
 
-If this is nil, the beginning of the buffer is used, which is
-always correct but tends to be slow.
-This is normally set via `font-lock-defaults'.
-This variable is semi-obsolete; we recommend setting
-`syntax-begin-function' instead.")
+If this is nil, Font Lock uses `syntax-begin-function' to move back
+outside of any comment, string, or sexp.  This variable is semi-obsolete;
+we recommend setting `syntax-begin-function' instead.
+
+This is normally set via `font-lock-defaults'.")
 
 (defvar font-lock-mark-block-function nil
   "*Non-nil means use this function to mark a block of text.
@@ -620,6 +609,7 @@ Major/minor modes can set this variable if they know which option applies.")
   ;; We use this to preserve or protect things when modifying text properties.
   (defmacro save-buffer-state (varlist &rest body)
     "Bind variables according to VARLIST and eval BODY restoring buffer state."
+    (declare (indent 1) (debug let))
     (let ((modified (make-symbol "modified")))
       `(let* ,(append varlist
                      `((,modified (buffer-modified-p))
@@ -634,8 +624,6 @@ Major/minor modes can set this variable if they know which option applies.")
           ,@body)
         (unless ,modified
           (restore-buffer-modified-p nil)))))
-  (put 'save-buffer-state 'lisp-indent-function 1)
-  (def-edebug-spec save-buffer-state let)
   ;;
   ;; Shut up the byte compiler.
   (defvar font-lock-face-attributes))  ; Obsolete but respected if set.
@@ -683,9 +671,22 @@ For example:
 adds two fontification patterns for C mode, to fontify `FIXME:' words, even in
 comments, and to fontify `and', `or' and `not' words as keywords.
 
-When used from a Lisp program (such as a minor mode), it is recommended to
-use nil for MODE (and place the call on a hook) to avoid subtle problems
-due to details of the implementation.
+The above procedure will only add the keywords for C mode, not
+for modes derived from C mode.  To add them for derived modes too,
+pass nil for MODE and add the call to c-mode-hook.
+
+For example:
+
+ (add-hook 'c-mode-hook
+  (lambda ()
+   (font-lock-add-keywords nil
+    '((\"\\\\\\=<\\\\(FIXME\\\\):\" 1 font-lock-warning-face prepend)
+      (\"\\\\\\=<\\\\(and\\\\|or\\\\|not\\\\)\\\\\\=>\" .
+       font-lock-keyword-face)))))
+
+The above procedure may fail to add keywords to derived modes if
+some involved major mode does not follow the standard conventions.
+File a bug report if this happens, so the major mode can be corrected.
 
 Note that some modes have specialized support for additional patterns, e.g.,
 see the variables `c-font-lock-extra-types', `c++-font-lock-extra-types',
@@ -704,7 +705,8 @@ see the variables `c-font-lock-extra-types', `c++-font-lock-extra-types',
         (font-lock-update-removed-keyword-alist mode keywords append))
        (t
         ;; Otherwise set or add the keywords now.
-        ;; This is a no-op if it has been done already in this buffer.
+        ;; This is a no-op if it has been done already in this buffer
+        ;; for the correct major mode.
         (font-lock-set-defaults)
         (let ((was-compiled (eq (car font-lock-keywords) t)))
           ;; Bring back the user-level (uncompiled) keywords.
@@ -774,9 +776,11 @@ see the variables `c-font-lock-extra-types', `c++-font-lock-extra-types',
 MODE should be a symbol, the major mode command name, such as `c-mode'
 or nil.  If nil, highlighting keywords are removed for the current buffer.
 
-When used from a Lisp program (such as a minor mode), it is recommended to
-use nil for MODE (and place the call on a hook) to avoid subtle problems
-due to details of the implementation."
+To make the removal apply to modes derived from MODE as well,
+pass nil for MODE and add the call to MODE-hook.  This may fail
+for some derived modes if some involved major mode does not
+follow the standard conventions.  File a bug report if this
+happens, so the major mode can be corrected."
   (cond (mode
         ;; Remove one keyword at the time.
         (dolist (keyword keywords)
@@ -889,7 +893,7 @@ The value of this variable is used when Font Lock mode is turned on."
                        'font-lock-after-change-function t)
           (set (make-local-variable 'font-lock-fontify-buffer-function)
                'jit-lock-refontify)
-          ;; Don't fontify eagerly (and don't abort is the buffer is large).
+          ;; Don't fontify eagerly (and don't abort if the buffer is large).
           (set (make-local-variable 'font-lock-fontified) t)
           ;; Use jit-lock.
           (jit-lock-register 'font-lock-fontify-region
@@ -1034,6 +1038,8 @@ a very meaningful entity to highlight.")
          ;; Use the fontification syntax table, if any.
          (when font-lock-syntax-table
            (set-syntax-table font-lock-syntax-table))
+          (goto-char beg)
+          (setq beg (line-beginning-position (- 1 font-lock-lines-before)))
          ;; check to see if we should expand the beg/end area for
          ;; proper multiline matches
          (when (and font-lock-multiline
@@ -1090,8 +1096,7 @@ what properties to clear before refontifying a region.")
       (save-match-data
        ;; Rescan between start of lines enclosing the region.
        (font-lock-fontify-region
-        (progn (goto-char beg)
-               (forward-line (- font-lock-lines-before)) (point))
+        (progn (goto-char beg) (forward-line 0) (point))
         (progn (goto-char end) (forward-line 1) (point)))))))
 
 (defun font-lock-fontify-block (&optional arg)
@@ -1351,7 +1356,7 @@ START should be at the beginning of a line."
                                    comment-start-skip))
                    (put-text-property beg (match-end 0) 'face
                                       font-lock-comment-delimiter-face)))
-             (if (looking-back comment-end-regexp (point-at-bol))
+             (if (looking-back comment-end-regexp (point-at-bol) t)
                  (put-text-property (match-beginning 0) (point) 'face
                                     font-lock-comment-delimiter-face))))
          (< (point) end))
@@ -1458,7 +1463,11 @@ LOUDLY, if non-nil, allows progress-meter bar."
       (while (and (< (point) end)
                  (if (stringp matcher)
                      (re-search-forward matcher end t)
-                   (funcall matcher end)))
+                   (funcall matcher end))
+                  ;; Beware empty string matches since they will
+                  ;; loop indefinitely.
+                  (or (> (point) (match-beginning 0))
+                      (progn (forward-char 1) t)))
        (when (and font-lock-multiline
                   (>= (point)
                       (save-excursion (goto-char (match-beginning 0))
@@ -1571,12 +1580,15 @@ A LEVEL of nil is equal to a LEVEL of 0, a LEVEL of t is equal to
 
 (defvar font-lock-set-defaults nil)    ; Whether we have set up defaults.
 
+(defvar font-lock-mode-major-mode)
 (defun font-lock-set-defaults ()
   "Set fontification defaults appropriately for this mode.
 Sets various variables using `font-lock-defaults' (or, if nil, using
 `font-lock-defaults-alist') and `font-lock-maximum-decoration'."
-  ;; Set fontification defaults iff not previously set.
-  (unless font-lock-set-defaults
+  ;; Set fontification defaults iff not previously set for correct major mode.
+  (unless (and font-lock-set-defaults
+              (eq font-lock-mode-major-mode major-mode))
+    (setq font-lock-mode-major-mode major-mode)
     (set (make-local-variable 'font-lock-set-defaults) t)
     (make-local-variable 'font-lock-fontified)
     (make-local-variable 'font-lock-multiline)
@@ -1807,6 +1819,16 @@ Sets various variables using `font-lock-defaults' (or, if nil, using
   "Font Lock mode face used to highlight preprocessor directives."
   :group 'font-lock-highlighting-faces)
 
+(defface font-lock-regexp-grouping-backslash
+  '((t :inherit bold))
+  "Font Lock mode face for backslashes in Lisp regexp grouping constructs."
+  :group 'font-lock-highlighting-faces)
+
+(defface font-lock-regexp-grouping-construct
+  '((t :inherit bold))
+  "Font Lock mode face used to highlight grouping constructs in Lisp regexps."
+  :group 'font-lock-highlighting-faces)
+
 ;;; End of Colour etc. support.
 \f
 ;;; Menu support.
@@ -2000,7 +2022,7 @@ This function could be MATCHER in a MATCH-ANCHORED `font-lock-keywords' item."
      `(;; Control structures.  Emacs Lisp forms.
        (,(concat
          "(" (regexp-opt
-              '("cond" "if" "while" "let" "let*"
+              '("cond" "if" "while" "while-no-input" "let" "let*"
                 "prog" "progn" "progv" "prog1" "prog2" "prog*"
                 "inline" "lambda" "save-restriction" "save-excursion"
                 "save-window-excursion" "save-selected-window"
@@ -2053,21 +2075,22 @@ This function could be MATCHER in a MATCH-ANCHORED `font-lock-keywords' item."
        ("\\<:\\sw+\\>" 0 font-lock-builtin-face)
        ;; ELisp and CLisp `&' keywords as types.
        ("\\&\\sw+\\>" . font-lock-type-face)
-       ;; Make regexp grouping constructs bold, so they stand out, but only in strings.
+       ;; ELisp regexp grouping constructs
        ((lambda (bound)
-         (if (re-search-forward "\\([\\][\\]\\)\\([(|)]\\)\\(\\?:\\)?" bound)
-              (let ((face (get-text-property (1- (point)) 'face)))
-                (if (listp face)
-                    (memq 'font-lock-string-face face)
-                  (eq 'font-lock-string-face face)))))
-       (1 font-lock-comment-face prepend) ; Should we introduce a lowlight face for this?
-                                       ; Ideally that would retain the color, dimmed 50%.
-       (2 'bold prepend)
-       (3 font-lock-type-face prepend t))
-       ;; Underline innermost grouping, so that you can more easily see what belongs together.
-       ;; 2005-05-12: Font-lock can go into an unbreakable endless loop on this -- something's broken.
-       ;;("[\\][\\][(]\\(?:\\?:\\)?\\(\\(?:[^\\\"]+\\|[\\]\\(?:[^\\]\\|[\\][^(]\\)\\)+?\\)[\\][\\][)]"
-        ;;1 'underline prepend)
+          (catch 'found
+            ;; The following loop is needed to continue searching after matches
+            ;; that do not occur in strings.  The associated regexp matches one
+            ;; of `\\\\' `\\(' `\\(?:' `\\|' `\\)'.  `\\\\' has been included to
+            ;; avoid highlighting, for example, `\\(' in `\\\\('.
+            (while (re-search-forward "\\(\\\\\\\\\\)\\(?:\\(\\\\\\\\\\)\\|\\((\\(?:\\?:\\)?\\|[|)]\\)\\)" bound t)
+              (unless (match-beginning 2)
+                (let ((face (get-text-property (1- (point)) 'face)))
+                  (when (or (and (listp face)
+                                 (memq 'font-lock-string-face face))
+                            (eq 'font-lock-string-face face))
+                    (throw 'found t)))))))
+        (1 'font-lock-regexp-grouping-backslash prepend)
+        (3 'font-lock-regexp-grouping-construct prepend))
 ;;;  This is too general -- rms.
 ;;;  A user complained that he has functions whose names start with `do'
 ;;;  and that they get the wrong color.