diff options
Diffstat (limited to 'lisp/font-lock.el')
| -rw-r--r-- | lisp/font-lock.el | 177 |
1 files changed, 152 insertions, 25 deletions
diff --git a/lisp/font-lock.el b/lisp/font-lock.el index f001a0bfaac..093780c3914 100644 --- a/lisp/font-lock.el +++ b/lisp/font-lock.el | |||
| @@ -893,7 +893,11 @@ The value of this variable is used when Font Lock mode is turned on." | |||
| 893 | (set (make-local-variable 'font-lock-fontified) t) | 893 | (set (make-local-variable 'font-lock-fontified) t) |
| 894 | ;; Use jit-lock. | 894 | ;; Use jit-lock. |
| 895 | (jit-lock-register 'font-lock-fontify-region | 895 | (jit-lock-register 'font-lock-fontify-region |
| 896 | (not font-lock-keywords-only)))))) | 896 | (not font-lock-keywords-only)) |
| 897 | ;; Tell jit-lock how we extend the region to refontify. | ||
| 898 | (add-hook 'jit-lock-after-change-extend-region-functions | ||
| 899 | 'font-lock-extend-jit-lock-region-after-change | ||
| 900 | nil t))))) | ||
| 897 | 901 | ||
| 898 | (defun font-lock-turn-off-thing-lock () | 902 | (defun font-lock-turn-off-thing-lock () |
| 899 | (cond ((and (boundp 'fast-lock-mode) fast-lock-mode) | 903 | (cond ((and (boundp 'fast-lock-mode) fast-lock-mode) |
| @@ -971,6 +975,21 @@ The value of this variable is used when Font Lock mode is turned on." | |||
| 971 | ;; directives correctly and cleanly. (It is the same problem as fontifying | 975 | ;; directives correctly and cleanly. (It is the same problem as fontifying |
| 972 | ;; multi-line strings and comments; regexps are not appropriate for the job.) | 976 | ;; multi-line strings and comments; regexps are not appropriate for the job.) |
| 973 | 977 | ||
| 978 | (defvar font-lock-extend-after-change-region-function nil | ||
| 979 | "A function that determines the region to refontify after a change. | ||
| 980 | |||
| 981 | This variable is either nil, or is a function that determines the | ||
| 982 | region to refontify after a change. | ||
| 983 | It is usually set by the major mode via `font-lock-defaults'. | ||
| 984 | Font-lock calls this function after each buffer change. | ||
| 985 | |||
| 986 | The function is given three parameters, the standard BEG, END, and OLD-LEN | ||
| 987 | from `after-change-functions'. It should return either a cons of the beginning | ||
| 988 | and end buffer positions \(in that order) of the region to refontify, or nil | ||
| 989 | \(which directs the caller to fontify a default region). | ||
| 990 | This function should preserve the match-data. | ||
| 991 | The region it returns may start or end in the middle of a line.") | ||
| 992 | |||
| 974 | (defun font-lock-fontify-buffer () | 993 | (defun font-lock-fontify-buffer () |
| 975 | "Fontify the current buffer the way the function `font-lock-mode' would." | 994 | "Fontify the current buffer the way the function `font-lock-mode' would." |
| 976 | (interactive) | 995 | (interactive) |
| @@ -1021,6 +1040,59 @@ The value of this variable is used when Font Lock mode is turned on." | |||
| 1021 | Useful for things like RMAIL and Info where the whole buffer is not | 1040 | Useful for things like RMAIL and Info where the whole buffer is not |
| 1022 | a very meaningful entity to highlight.") | 1041 | a very meaningful entity to highlight.") |
| 1023 | 1042 | ||
| 1043 | |||
| 1044 | (defvar font-lock-beg) (defvar font-lock-end) | ||
| 1045 | (defvar font-lock-extend-region-functions | ||
| 1046 | '(font-lock-extend-region-wholelines | ||
| 1047 | ;; This use of font-lock-multiline property is unreliable but is just | ||
| 1048 | ;; a handy heuristic: in case you don't have a function that does | ||
| 1049 | ;; /identification/ of multiline elements, you may still occasionally | ||
| 1050 | ;; discover them by accident (or you may /identify/ them but not in all | ||
| 1051 | ;; cases), in which case the font-lock-multiline property can help make | ||
| 1052 | ;; sure you will properly *re*identify them during refontification. | ||
| 1053 | font-lock-extend-region-multiline) | ||
| 1054 | "Special hook run just before proceeding to fontify a region. | ||
| 1055 | This is used to allow major modes to help font-lock find safe buffer positions | ||
| 1056 | as beginning and end of the fontified region. Its most common use is to solve | ||
| 1057 | the problem of /identification/ of multiline elements by providing a function | ||
| 1058 | that tries to find such elements and move the boundaries such that they do | ||
| 1059 | not fall in the middle of one. | ||
| 1060 | Each function is called with no argument; it is expected to adjust the | ||
| 1061 | dynamically bound variables `font-lock-beg' and `font-lock-end'; and return | ||
| 1062 | non-nil iff it did make such an adjustment. | ||
| 1063 | These functions are run in turn repeatedly until they all return nil. | ||
| 1064 | Put first the functions more likely to cause a change and cheaper to compute.") | ||
| 1065 | ;; Mark it as a special hook which doesn't use any global setting | ||
| 1066 | ;; (i.e. doesn't obey the element t in the buffer-local value). | ||
| 1067 | (make-variable-buffer-local 'font-lock-extend-region-functions) | ||
| 1068 | |||
| 1069 | (defun font-lock-extend-region-multiline () | ||
| 1070 | "Move fontification boundaries away from any `font-lock-multiline' property." | ||
| 1071 | (let ((changed nil)) | ||
| 1072 | (when (and (> font-lock-beg (point-min)) | ||
| 1073 | (get-text-property (1- font-lock-beg) 'font-lock-multiline)) | ||
| 1074 | (setq changed t) | ||
| 1075 | (setq font-lock-beg (or (previous-single-property-change | ||
| 1076 | font-lock-beg 'font-lock-multiline) | ||
| 1077 | (point-min)))) | ||
| 1078 | ;; | ||
| 1079 | (when (get-text-property font-lock-end 'font-lock-multiline) | ||
| 1080 | (setq changed t) | ||
| 1081 | (setq font-lock-end (or (text-property-any font-lock-end (point-max) | ||
| 1082 | 'font-lock-multiline nil) | ||
| 1083 | (point-max)))) | ||
| 1084 | changed)) | ||
| 1085 | |||
| 1086 | |||
| 1087 | (defun font-lock-extend-region-wholelines () | ||
| 1088 | "Move fontification boundaries to beginning of lines." | ||
| 1089 | (let ((changed nil)) | ||
| 1090 | (goto-char font-lock-beg) | ||
| 1091 | (unless (bolp) (setq changed t font-lock-beg (line-beginning-position))) | ||
| 1092 | (goto-char font-lock-end) | ||
| 1093 | (unless (bolp) (setq changed t font-lock-end (line-beginning-position 2))) | ||
| 1094 | changed)) | ||
| 1095 | |||
| 1024 | (defun font-lock-default-fontify-region (beg end loudly) | 1096 | (defun font-lock-default-fontify-region (beg end loudly) |
| 1025 | (save-buffer-state | 1097 | (save-buffer-state |
| 1026 | ((parse-sexp-lookup-properties | 1098 | ((parse-sexp-lookup-properties |
| @@ -1032,24 +1104,21 @@ a very meaningful entity to highlight.") | |||
| 1032 | ;; Use the fontification syntax table, if any. | 1104 | ;; Use the fontification syntax table, if any. |
| 1033 | (when font-lock-syntax-table | 1105 | (when font-lock-syntax-table |
| 1034 | (set-syntax-table font-lock-syntax-table)) | 1106 | (set-syntax-table font-lock-syntax-table)) |
| 1035 | (goto-char beg) | 1107 | ;; Extend the region to fontify so that it starts and ends at |
| 1036 | (setq beg (line-beginning-position)) | 1108 | ;; safe places. |
| 1037 | ;; check to see if we should expand the beg/end area for | 1109 | (let ((funs font-lock-extend-region-functions) |
| 1038 | ;; proper multiline matches | 1110 | (font-lock-beg beg) |
| 1039 | (when (and (> beg (point-min)) | 1111 | (font-lock-end end)) |
| 1040 | (get-text-property (1- beg) 'font-lock-multiline)) | 1112 | (while funs |
| 1041 | ;; We are just after or in a multiline match. | 1113 | (setq funs (if (or (not (funcall (car funs))) |
| 1042 | (setq beg (or (previous-single-property-change | 1114 | (eq funs font-lock-extend-region-functions)) |
| 1043 | beg 'font-lock-multiline) | 1115 | (cdr funs) |
| 1044 | (point-min))) | 1116 | ;; If there's been a change, we should go through |
| 1045 | (goto-char beg) | 1117 | ;; the list again since this new position may |
| 1046 | (setq beg (line-beginning-position))) | 1118 | ;; warrant a different answer from one of the fun |
| 1047 | (setq end (or (text-property-any end (point-max) | 1119 | ;; we've already seen. |
| 1048 | 'font-lock-multiline nil) | 1120 | font-lock-extend-region-functions))) |
| 1049 | (point-max))) | 1121 | (setq beg font-lock-beg end font-lock-end)) |
| 1050 | (goto-char end) | ||
| 1051 | ;; Round up to a whole line. | ||
| 1052 | (unless (bolp) (setq end (line-beginning-position 2))) | ||
| 1053 | ;; Now do the fontification. | 1122 | ;; Now do the fontification. |
| 1054 | (font-lock-unfontify-region beg end) | 1123 | (font-lock-unfontify-region beg end) |
| 1055 | (when font-lock-syntactic-keywords | 1124 | (when font-lock-syntactic-keywords |
| @@ -1083,19 +1152,77 @@ what properties to clear before refontifying a region.") | |||
| 1083 | 1152 | ||
| 1084 | ;; Called when any modification is made to buffer text. | 1153 | ;; Called when any modification is made to buffer text. |
| 1085 | (defun font-lock-after-change-function (beg end old-len) | 1154 | (defun font-lock-after-change-function (beg end old-len) |
| 1086 | (let ((inhibit-point-motion-hooks t) | 1155 | (save-excursion |
| 1087 | (inhibit-quit t) | 1156 | (let ((inhibit-point-motion-hooks t) |
| 1088 | (region (font-lock-extend-region beg end old-len))) | 1157 | (inhibit-quit t) |
| 1089 | (save-excursion | 1158 | (region (if font-lock-extend-after-change-region-function |
| 1159 | (funcall font-lock-extend-after-change-region-function | ||
| 1160 | beg end old-len)))) | ||
| 1090 | (save-match-data | 1161 | (save-match-data |
| 1091 | (if region | 1162 | (if region |
| 1092 | ;; Fontify the region the major mode has specified. | 1163 | ;; Fontify the region the major mode has specified. |
| 1093 | (setq beg (car region) end (cdr region)) | 1164 | (setq beg (car region) end (cdr region)) |
| 1094 | ;; Fontify the whole lines which enclose the region. | 1165 | ;; Fontify the whole lines which enclose the region. |
| 1095 | (setq beg (progn (goto-char beg) (line-beginning-position)) | 1166 | ;; Actually, this is not needed because |
| 1096 | end (progn (goto-char end) (line-beginning-position 2)))) | 1167 | ;; font-lock-default-fontify-region already rounds up to a whole |
| 1168 | ;; number of lines. | ||
| 1169 | ;; (setq beg (progn (goto-char beg) (line-beginning-position)) | ||
| 1170 | ;; end (progn (goto-char end) (line-beginning-position 2))) | ||
| 1171 | ) | ||
| 1097 | (font-lock-fontify-region beg end))))) | 1172 | (font-lock-fontify-region beg end))))) |
| 1098 | 1173 | ||
| 1174 | (defvar jit-lock-start) (defvar jit-lock-end) | ||
| 1175 | (defun font-lock-extend-jit-lock-region-after-change (beg end old-len) | ||
| 1176 | "Function meant for `jit-lock-after-change-extend-region-functions'. | ||
| 1177 | This function does 2 things: | ||
| 1178 | - extend the region so that it not only includes the part that was modified | ||
| 1179 | but also the surrounding text whose highlighting may change as a consequence. | ||
| 1180 | - anticipate (part of) the region extension that will happen later in | ||
| 1181 | `font-lock-default-fontify-region', in order to avoid the need for | ||
| 1182 | double-redisplay in `jit-lock-fontify-now'." | ||
| 1183 | (save-excursion | ||
| 1184 | ;; First extend the region as font-lock-after-change-function would. | ||
| 1185 | (let ((region (if font-lock-extend-after-change-region-function | ||
| 1186 | (funcall font-lock-extend-after-change-region-function | ||
| 1187 | beg end old-len)))) | ||
| 1188 | (if region | ||
| 1189 | (setq beg (min jit-lock-start (car region)) | ||
| 1190 | end (max jit-lock-end (cdr region)))) | ||
| 1191 | ;; Then extend the region obeying font-lock-multiline properties, | ||
| 1192 | ;; indicating which part of the buffer needs to be refontified. | ||
| 1193 | ;; !!! This is the *main* user of font-lock-multiline property !!! | ||
| 1194 | ;; font-lock-after-change-function could/should also do that, but it | ||
| 1195 | ;; doesn't need to because font-lock-default-fontify-region does | ||
| 1196 | ;; it anyway. Here OTOH we have no guarantee that | ||
| 1197 | ;; font-lock-default-fontify-region will be executed on this region | ||
| 1198 | ;; any time soon. | ||
| 1199 | ;; Note: contrary to font-lock-default-fontify-region, we do not do | ||
| 1200 | ;; any loop here because we are not looking for a safe spot: we just | ||
| 1201 | ;; mark the text whose appearance may need to change as a result of | ||
| 1202 | ;; the buffer modification. | ||
| 1203 | (when (and (> beg (point-min)) | ||
| 1204 | (get-text-property (1- beg) 'font-lock-multiline)) | ||
| 1205 | (setq beg (or (previous-single-property-change | ||
| 1206 | beg 'font-lock-multiline) | ||
| 1207 | (point-min)))) | ||
| 1208 | (setq end (or (text-property-any end (point-max) | ||
| 1209 | 'font-lock-multiline nil) | ||
| 1210 | (point-max))) | ||
| 1211 | ;; Finally, pre-enlarge the region to a whole number of lines, to try | ||
| 1212 | ;; and anticipate what font-lock-default-fontify-region will do, so as to | ||
| 1213 | ;; avoid double-redisplay. | ||
| 1214 | ;; We could just run `font-lock-extend-region-functions', but since | ||
| 1215 | ;; the only purpose is to avoid the double-redisplay, we prefer to | ||
| 1216 | ;; do here only the part that is cheap and most likely to be useful. | ||
| 1217 | (when (memq 'font-lock-extend-region-wholelines | ||
| 1218 | font-lock-extend-region-functions) | ||
| 1219 | (goto-char beg) | ||
| 1220 | (forward-line 0) | ||
| 1221 | (setq jit-lock-start (min jit-lock-start (point))) | ||
| 1222 | (goto-char end) | ||
| 1223 | (forward-line 1) | ||
| 1224 | (setq jit-lock-end (max jit-lock-end (point))))))) | ||
| 1225 | |||
| 1099 | (defun font-lock-fontify-block (&optional arg) | 1226 | (defun font-lock-fontify-block (&optional arg) |
| 1100 | "Fontify some lines the way `font-lock-fontify-buffer' would. | 1227 | "Fontify some lines the way `font-lock-fontify-buffer' would. |
| 1101 | The lines could be a function or paragraph, or a specified number of lines. | 1228 | The lines could be a function or paragraph, or a specified number of lines. |