| | 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.") |
|---|
| | 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 (bobp) (setq changed t font-lock-beg (line-beginning-position))) |
|---|
| | 1092 | (goto-char font-lock-end) |
|---|
| | 1093 | (unless (bobp) (setq changed t font-lock-end (line-beginning-position 2))) |
|---|
| | 1094 | changed)) |
|---|
| | 1095 | |
|---|
| 1035 | | (goto-char beg) |
|---|
| 1036 | | (setq beg (line-beginning-position)) |
|---|
| 1037 | | ;; check to see if we should expand the beg/end area for |
|---|
| 1038 | | ;; proper multiline matches |
|---|
| 1039 | | (when (and (> beg (point-min)) |
|---|
| 1040 | | (get-text-property (1- beg) 'font-lock-multiline)) |
|---|
| 1041 | | ;; We are just after or in a multiline match. |
|---|
| 1042 | | (setq beg (or (previous-single-property-change |
|---|
| 1043 | | beg 'font-lock-multiline) |
|---|
| 1044 | | (point-min))) |
|---|
| 1045 | | (goto-char beg) |
|---|
| 1046 | | (setq beg (line-beginning-position))) |
|---|
| 1047 | | (setq end (or (text-property-any end (point-max) |
|---|
| 1048 | | 'font-lock-multiline nil) |
|---|
| 1049 | | (point-max))) |
|---|
| 1050 | | (goto-char end) |
|---|
| 1051 | | ;; Round up to a whole line. |
|---|
| 1052 | | (unless (bolp) (setq end (line-beginning-position 2))) |
|---|
| | 1107 | ;; Extend the region to fontify so that it starts and ends at |
|---|
| | 1108 | ;; safe places. |
|---|
| | 1109 | (let ((funs font-lock-extend-region-functions) |
|---|
| | 1110 | (font-lock-beg beg) |
|---|
| | 1111 | (font-lock-end end)) |
|---|
| | 1112 | (while funs |
|---|
| | 1113 | (setq funs (if (or (not (funcall (car funs))) |
|---|
| | 1114 | (eq funs font-lock-extend-region-functions)) |
|---|
| | 1115 | (cdr funs) |
|---|
| | 1116 | ;; If there's been a change, we should go through |
|---|
| | 1117 | ;; the list again since this new position may |
|---|
| | 1118 | ;; warrant a different answer from one of the fun |
|---|
| | 1119 | ;; we've already seen. |
|---|
| | 1120 | font-lock-extend-region-functions))) |
|---|
| | 1121 | (setq beg font-lock-beg end font-lock-end)) |
|---|
| | 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))))))) |
|---|