X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/05a1066ff0521af95b3761376c853d96312ca2f3..4837b516ea56c6cc2b3ce823b04078b10b2defc6:/lisp/font-lock.el diff --git a/lisp/font-lock.el b/lisp/font-lock.el index 0cad924f20..6bc5fd8716 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el @@ -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, 2006 Free Software Foundation, Inc. +;; 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. ;; Author: jwz, then rms, then sm ;; Maintainer: FSF @@ -11,7 +11,7 @@ ;; GNU Emacs 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) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. ;; GNU Emacs is distributed in the hope that it will be useful, @@ -355,7 +355,7 @@ Each element in a user-level keywords list should have one of these forms: where MATCHER can be either the regexp to search for, or the function name to call to make the search (called with one argument, the limit of the search; -it should return non-nil, move point, and set `match-data' appropriately iff +it should return non-nil, move point, and set `match-data' appropriately if it succeeds; like `re-search-forward' would). MATCHER regexps can be generated via the function `regexp-opt'. @@ -468,6 +468,7 @@ they are added at the end. This is normally set via `font-lock-add-keywords' and `font-lock-remove-keywords'.") +(put 'font-lock-keywords-alist 'risky-local-variable t) (defvar font-lock-removed-keywords-alist nil "Alist of `font-lock-keywords' elements to be removed for major modes. @@ -697,6 +698,14 @@ see the variables `c-font-lock-extra-types', `c++-font-lock-extra-types', ;; contain the new keywords. (font-lock-update-removed-keyword-alist mode keywords how)) (t + (when (and font-lock-mode + (not (or font-lock-keywords font-lock-defaults))) + ;; The major mode has not set any keywords, so when we enabled + ;; font-lock-mode it only enabled the font-core.el part, not the + ;; font-lock-mode-internal. Try again. + (font-lock-mode -1) + (set (make-local-variable 'font-lock-defaults) '(nil t)) + (font-lock-mode 1)) ;; Otherwise set or add the keywords now. ;; This is a no-op if it has been done already in this buffer ;; for the correct major mode. @@ -718,7 +727,7 @@ see the variables `c-font-lock-extra-types', `c++-font-lock-extra-types', ;; If the keywords were compiled before, compile them again. (if was-compiled (setq font-lock-keywords - (font-lock-compile-keywords font-lock-keywords t))))))) + (font-lock-compile-keywords font-lock-keywords))))))) (defun font-lock-update-removed-keyword-alist (mode keywords how) "Update `font-lock-removed-keywords-alist' when adding new KEYWORDS to MODE." @@ -825,7 +834,7 @@ happens, so the major mode can be corrected." ;; If the keywords were compiled before, compile them again. (if was-compiled (setq font-lock-keywords - (font-lock-compile-keywords font-lock-keywords t))))))) + (font-lock-compile-keywords font-lock-keywords))))))) ;;; Font Lock Support mode. @@ -976,7 +985,7 @@ The value of this variable is used when Font Lock mode is turned on." ;; multi-line strings and comments; regexps are not appropriate for the job.) (defvar font-lock-extend-after-change-region-function nil - "A function that determines the region to fontify after a change. + "A function that determines the region to refontify after a change. This variable is either nil, or is a function that determines the region to refontify after a change. @@ -985,7 +994,7 @@ Font-lock calls this function after each buffer change. The function is given three parameters, the standard BEG, END, and OLD-LEN from `after-change-functions'. It should return either a cons of the beginning -and end buffer positions \(in that order) of the region to fontify, or nil +and end buffer positions \(in that order) of the region to refontify, or nil \(which directs the caller to fontify a default region). This function should preserve the match-data. The region it returns may start or end in the middle of a line.") @@ -1044,6 +1053,12 @@ a very meaningful entity to highlight.") (defvar font-lock-beg) (defvar font-lock-end) (defvar font-lock-extend-region-functions '(font-lock-extend-region-wholelines + ;; This use of font-lock-multiline property is unreliable but is just + ;; a handy heuristic: in case you don't have a function that does + ;; /identification/ of multiline elements, you may still occasionally + ;; discover them by accident (or you may /identify/ them but not in all + ;; cases), in which case the font-lock-multiline property can help make + ;; sure you will properly *re*identify them during refontification. font-lock-extend-region-multiline) "Special hook run just before proceeding to fontify a region. This is used to allow major modes to help font-lock find safe buffer positions @@ -1053,7 +1068,7 @@ that tries to find such elements and move the boundaries such that they do not fall in the middle of one. Each function is called with no argument; it is expected to adjust the dynamically bound variables `font-lock-beg' and `font-lock-end'; and return -non-nil iff it did make such an adjustment. +non-nil if it did make such an adjustment. These functions are run in turn repeatedly until they all return nil. Put first the functions more likely to cause a change and cheaper to compute.") ;; Mark it as a special hook which doesn't use any global setting @@ -1069,22 +1084,25 @@ Put first the functions more likely to cause a change and cheaper to compute.") (setq font-lock-beg (or (previous-single-property-change font-lock-beg 'font-lock-multiline) (point-min)))) - ;; + ;; (when (get-text-property font-lock-end 'font-lock-multiline) (setq changed t) (setq font-lock-end (or (text-property-any font-lock-end (point-max) 'font-lock-multiline nil) (point-max)))) changed)) - - + (defun font-lock-extend-region-wholelines () "Move fontification boundaries to beginning of lines." (let ((changed nil)) (goto-char font-lock-beg) - (unless (bobp) (setq changed t font-lock-beg (line-beginning-position))) + (unless (bolp) + (setq changed t font-lock-beg (line-beginning-position))) (goto-char font-lock-end) - (unless (bobp) (setq changed t font-lock-end (line-beginning-position 2))) + (unless (bolp) + (unless (eq font-lock-end + (setq font-lock-end (line-beginning-position 2))) + (setq changed t))) changed)) (defun font-lock-default-fontify-region (beg end loudly) @@ -1162,11 +1180,23 @@ what properties to clear before refontifying a region.") ;; number of lines. ;; (setq beg (progn (goto-char beg) (line-beginning-position)) ;; end (progn (goto-char end) (line-beginning-position 2))) - ) + (unless (eq end (point-max)) + ;; Rounding up to a whole number of lines should include the + ;; line right after `end'. Typical case: the first char of + ;; the line was deleted. Or a \n was inserted in the middle + ;; of a line. + (setq end (1+ end)))) (font-lock-fontify-region beg end))))) (defvar jit-lock-start) (defvar jit-lock-end) (defun font-lock-extend-jit-lock-region-after-change (beg end old-len) + "Function meant for `jit-lock-after-change-extend-region-functions'. +This function does 2 things: +- extend the region so that it not only includes the part that was modified + but also the surrounding text whose highlighting may change as a consequence. +- anticipate (part of) the region extension that will happen later in + `font-lock-default-fontify-region', in order to avoid the need for + double-redisplay in `jit-lock-fontify-now'." (save-excursion ;; First extend the region as font-lock-after-change-function would. (let ((region (if font-lock-extend-after-change-region-function @@ -1177,25 +1207,46 @@ what properties to clear before refontifying a region.") end (max jit-lock-end (cdr region)))) ;; Then extend the region obeying font-lock-multiline properties, ;; indicating which part of the buffer needs to be refontified. + ;; !!! This is the *main* user of font-lock-multiline property !!! + ;; font-lock-after-change-function could/should also do that, but it + ;; doesn't need to because font-lock-default-fontify-region does + ;; it anyway. Here OTOH we have no guarantee that + ;; font-lock-default-fontify-region will be executed on this region + ;; any time soon. + ;; Note: contrary to font-lock-default-fontify-region, we do not do + ;; any loop here because we are not looking for a safe spot: we just + ;; mark the text whose appearance may need to change as a result of + ;; the buffer modification. (when (and (> beg (point-min)) (get-text-property (1- beg) 'font-lock-multiline)) (setq beg (or (previous-single-property-change beg 'font-lock-multiline) (point-min)))) - (setq end (or (text-property-any end (point-max) - 'font-lock-multiline nil) - (point-max))) + (when (< end (point-max)) + (setq end + (if (get-text-property end 'font-lock-multiline) + (or (text-property-any end (point-max) + 'font-lock-multiline nil) + (point-max)) + ;; Rounding up to a whole number of lines should include the + ;; line right after `end'. Typical case: the first char of + ;; the line was deleted. Or a \n was inserted in the middle + ;; of a line. + (1+ end)))) ;; Finally, pre-enlarge the region to a whole number of lines, to try - ;; and predict what font-lock-default-fontify-region will do, so as to + ;; and anticipate what font-lock-default-fontify-region will do, so as to ;; avoid double-redisplay. + ;; We could just run `font-lock-extend-region-functions', but since + ;; the only purpose is to avoid the double-redisplay, we prefer to + ;; do here only the part that is cheap and most likely to be useful. (when (memq 'font-lock-extend-region-wholelines font-lock-extend-region-functions) (goto-char beg) - (forward-line 0) - (setq jit-lock-start (min jit-lock-start (point))) + (setq jit-lock-start (min jit-lock-start (line-beginning-position))) (goto-char end) - (forward-line 1) - (setq jit-lock-end (max jit-lock-end (point))))))) + (setq jit-lock-end + (max jit-lock-end + (if (bolp) (point) (line-beginning-position 2)))))))) (defun font-lock-fontify-block (&optional arg) "Fontify some lines the way `font-lock-fontify-buffer' would. @@ -1388,7 +1439,8 @@ START should be at the beginning of a line." ;; If `font-lock-syntactic-keywords' is not compiled, compile it. (unless (eq (car font-lock-syntactic-keywords) t) (setq font-lock-syntactic-keywords (font-lock-compile-keywords - font-lock-syntactic-keywords))) + font-lock-syntactic-keywords + t))) ;; Get down to business. (let ((case-fold-search font-lock-keywords-case-fold-search) (keywords (cddr font-lock-syntactic-keywords)) @@ -1544,7 +1596,7 @@ START should be at the beginning of a line. LOUDLY, if non-nil, allows progress-meter bar." (unless (eq (car font-lock-keywords) t) (setq font-lock-keywords - (font-lock-compile-keywords font-lock-keywords t))) + (font-lock-compile-keywords font-lock-keywords))) (let ((case-fold-search font-lock-keywords-case-fold-search) (keywords (cddr font-lock-keywords)) (bufname (buffer-name)) (count 0) @@ -1600,12 +1652,12 @@ LOUDLY, if non-nil, allows progress-meter bar." ;; Various functions. -(defun font-lock-compile-keywords (keywords &optional regexp) +(defun font-lock-compile-keywords (keywords &optional syntactic-keywords) "Compile KEYWORDS into the form (t KEYWORDS COMPILED...) Here each COMPILED is of the form (MATCHER HIGHLIGHT ...) as shown in the `font-lock-keywords' doc string. -If REGEXP is non-nil, it means these keywords are used for -`font-lock-keywords' rather than for `font-lock-syntactic-keywords'." +If SYNTACTIC-KEYWORDS is non-nil, it means these keywords are used for +`font-lock-syntactic-keywords' rather than for `font-lock-keywords'." (if (not font-lock-set-defaults) ;; This should never happen. But some external packages sometimes ;; call font-lock in unexpected and incorrect ways. It's important to @@ -1618,10 +1670,12 @@ If REGEXP is non-nil, it means these keywords are used for (setq keywords (cons t (cons keywords (mapcar 'font-lock-compile-keyword keywords)))) - (if (and regexp - (eq (or syntax-begin-function - font-lock-beginning-of-syntax-function) - 'beginning-of-defun) + (if (and (not syntactic-keywords) + (let ((beg-function + (or font-lock-beginning-of-syntax-function + syntax-begin-function))) + (or (eq beg-function 'beginning-of-defun) + (get beg-function 'font-lock-syntax-paren-check))) (not beginning-of-defun-function)) ;; Try to detect when a string or comment contains something that ;; looks like a defun and would thus confuse font-lock. @@ -1692,7 +1746,7 @@ A LEVEL of nil is equal to a LEVEL of 0, a LEVEL of t is equal to "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 for correct major mode. + ;; Set fontification defaults if 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) @@ -1748,7 +1802,7 @@ Sets various variables using `font-lock-defaults' (or, if nil, using ;; Now compile the keywords. (unless (eq (car font-lock-keywords) t) (setq font-lock-keywords - (font-lock-compile-keywords font-lock-keywords t)))))) + (font-lock-compile-keywords font-lock-keywords)))))) ;;; Colour etc. support. @@ -2145,7 +2199,7 @@ other modes in which C preprocessor directives are used. e.g. `asm-mode' and "\\(advice\\|alias\\|generic\\|macro\\*?\\|method\\|" "setf\\|subst\\*?\\|un\\*?\\|" "ine-\\(condition\\|" - "\\(?:derived\\|\\(?:global-\\)?minor\\|generic\\)-mode\\|" + "\\(?:derived\\|\\(?:global\\(?:ized\\)?-\\)?minor\\|generic\\)-mode\\|" "method-combination\\|setf-expander\\|skeleton\\|widget\\|" "function\\|\\(compiler\\|modify\\|symbol\\)-macro\\)\\)\\|" ;; Variable declarations. @@ -2181,7 +2235,7 @@ other modes in which C preprocessor directives are used. e.g. `asm-mode' and "condition-case" "track-mouse" "eval-after-load" "eval-and-compile" "eval-when-compile" "eval-when" "eval-at-startup" "eval-next-after-load" - "with-category-table" + "with-case-table" "with-category-table" "with-current-buffer" "with-electric-help" "with-local-quit" "with-no-warnings" "with-output-to-string" "with-output-to-temp-buffer"