aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2018-06-08 16:42:18 +0000
committerAlan Mackenzie2018-06-08 16:42:18 +0000
commitfe06f643b2808b198bb58bda04a8c863e55a2a56 (patch)
tree6b6cefea3df9647cea1a3315f59c7936d56965e3
parentdb353b8649cdae54146308e4c875e53d02b0aaee (diff)
downloademacs-fe06f643b2808b198bb58bda04a8c863e55a2a56.tar.gz
emacs-fe06f643b2808b198bb58bda04a8c863e55a2a56.zip
CC Mode: Fontify unbalanced quotes in unconstrained multiline strings, etc.
("Unconstrained" meaning that every string is multiline, without needing such special marking as used by Pike Mode.) * lisp/progmodes/cc-mode.el (c-pps-to-string-delim): Don't process the char before BOB. (c-multiline-string-check-final-quote): New function. (c-bc-changed-stringiness): New variable. (c-before-change-check-unbalanced-strings): Add handling for unconstrained multiline strings. (c-after-change-re-mark-unbalanced-strings): Add handling for unconstrained multiline strings. Handle escaped double quotes more accurately.
-rw-r--r--lisp/progmodes/cc-mode.el214
1 files changed, 147 insertions, 67 deletions
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index a1411ad5ea2..e619fac43f2 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -1110,13 +1110,56 @@ Note that the style variables are always made local to the buffer."
1110 (goto-char start) 1110 (goto-char start)
1111 (while (progn 1111 (while (progn
1112 (parse-partial-sexp (point) end nil nil st-s 'syntax-table) 1112 (parse-partial-sexp (point) end nil nil st-s 'syntax-table)
1113 (c-clear-char-property (1- (point)) 'syntax-table) 1113 (unless (bobp)
1114 (c-clear-char-property (1- (point)) 'syntax-table))
1114 (setq st-pos (point)) 1115 (setq st-pos (point))
1115 (and (< (point) end) 1116 (and (< (point) end)
1116 (not (eq (char-before) ?\"))))) 1117 (not (eq (char-before) ?\")))))
1117 (goto-char (min no-st-pos st-pos)) 1118 (goto-char (min no-st-pos st-pos))
1118 nil)) 1119 nil))
1119 1120
1121(defun c-multiline-string-check-final-quote ()
1122 ;; Check that the final quote in the buffer is correctly marked or not with
1123 ;; a string-fence syntax-table text propery. The return value has no
1124 ;; significance.
1125 (let (pos-ll pos-lt)
1126 (save-excursion
1127 (goto-char (point-max))
1128 (skip-chars-backward "^\"")
1129 (while
1130 (and
1131 (not (bobp))
1132 (cond
1133 ((progn
1134 (setq pos-ll (c-literal-limits)
1135 pos-lt (c-literal-type pos-ll))
1136 (memq pos-lt '(c c++)))
1137 ;; In a comment.
1138 (goto-char (car pos-ll)))
1139 ((save-excursion
1140 (backward-char) ; over "
1141 (eq (logand (skip-chars-backward "\\\\") 1) 1))
1142 ;; At an escaped string.
1143 (backward-char)
1144 t)
1145 (t
1146 ;; At a significant "
1147 (c-clear-char-property (1- (point)) 'syntax-table)
1148 (setq pos-ll (c-literal-limits)
1149 pos-lt (c-literal-type pos-ll))
1150 nil)))
1151 (skip-chars-backward "^\""))
1152 (cond
1153 ((bobp))
1154 ((eq pos-lt 'string)
1155 (c-put-char-property (1- (point)) 'syntax-table '(15)))
1156 (t nil)))))
1157
1158(defvar c-bc-changed-stringiness nil)
1159;; Non-nil when, in a before-change function, the deletion of a range of text
1160;; will change the "stringiness" of the subsequent text. Only used when
1161;; `c-multiline-sting-start-char' is a non-nil value which isn't a character.
1162
1120(defun c-before-change-check-unbalanced-strings (beg end) 1163(defun c-before-change-check-unbalanced-strings (beg end)
1121 ;; If BEG or END is inside an unbalanced string, remove the syntax-table 1164 ;; If BEG or END is inside an unbalanced string, remove the syntax-table
1122 ;; text property from respectively the start or end of the string. Also 1165 ;; text property from respectively the start or end of the string. Also
@@ -1175,6 +1218,18 @@ Note that the style variables are always made local to the buffer."
1175 (< (point) (point-max)))))) 1218 (< (point) (point-max))))))
1176 (setq c-new-END (max (point) c-new-END))) 1219 (setq c-new-END (max (point) c-new-END)))
1177 1220
1221 (c-multiline-string-start-char
1222 (setq c-bc-changed-stringiness
1223 (not (eq (eq end-literal-type 'string)
1224 (eq beg-literal-type 'string))))
1225 ;; Deal with deletion of backslashes before "s.
1226 (goto-char end)
1227 (if (and (looking-at "\\\\*\"")
1228 (eq (logand (skip-chars-backward "\\\\" beg) 1) 1))
1229 (setq c-bc-changed-stringiness (not c-bc-changed-stringiness)))
1230 (if (eq beg-literal-type 'string)
1231 (setq c-new-BEG (min (car beg-limits) c-new-BEG))))
1232
1178 ((< c-new-END (point-max)) 1233 ((< c-new-END (point-max))
1179 (goto-char (1+ c-new-END)) ; might be a newline. 1234 (goto-char (1+ c-new-END)) ; might be a newline.
1180 ;; In the following regexp, the initial \n caters for a newline getting 1235 ;; In the following regexp, the initial \n caters for a newline getting
@@ -1183,7 +1238,6 @@ Note that the style variables are always made local to the buffer."
1183 nil t) 1238 nil t)
1184 ;; We're at an EOLL or point-max. 1239 ;; We're at an EOLL or point-max.
1185 (setq c-new-END (min (1+ (point)) (point-max))) 1240 (setq c-new-END (min (1+ (point)) (point-max)))
1186 ;; FIXME!!! Write a clever comment here.
1187 (goto-char c-new-END) 1241 (goto-char c-new-END)
1188 (if (equal (c-get-char-property (1- (point)) 'syntax-table) '(15)) 1242 (if (equal (c-get-char-property (1- (point)) 'syntax-table) '(15))
1189 (if (memq (char-before) '(?\n ?\r)) 1243 (if (memq (char-before) '(?\n ?\r))
@@ -1202,14 +1256,16 @@ Note that the style variables are always made local to the buffer."
1202 (if (c-search-backward-char-property 'syntax-table '(15) c-new-BEG) 1256 (if (c-search-backward-char-property 'syntax-table '(15) c-new-BEG)
1203 (c-clear-char-property (point) 'syntax-table)))) 1257 (c-clear-char-property (point) 'syntax-table))))
1204 1258
1205 (when (eq end-literal-type 'string) 1259 (unless (and c-multiline-string-start-char
1206 (c-clear-char-property (1- (cdr end-limits)) 'syntax-table)) 1260 (not (c-characterp c-multiline-string-start-char)))
1261 (when (eq end-literal-type 'string)
1262 (c-clear-char-property (1- (cdr end-limits)) 'syntax-table))
1207 1263
1208 (when (eq beg-literal-type 'string) 1264 (when (eq beg-literal-type 'string)
1209 (setq c-new-BEG (min c-new-BEG (car beg-limits))) 1265 (setq c-new-BEG (min c-new-BEG (car beg-limits)))
1210 (c-clear-char-property (car beg-limits) 'syntax-table)))) 1266 (c-clear-char-property (car beg-limits) 'syntax-table)))))
1211 1267
1212(defun c-after-change-re-mark-unbalanced-strings (beg _end _old-len) 1268(defun c-after-change-re-mark-unbalanced-strings (beg end _old-len)
1213 ;; Mark any unbalanced strings in the region (c-new-BEG c-new-END) with 1269 ;; Mark any unbalanced strings in the region (c-new-BEG c-new-END) with
1214 ;; string fence syntax-table text properties. 1270 ;; string fence syntax-table text properties.
1215 ;; 1271 ;;
@@ -1218,66 +1274,90 @@ Note that the style variables are always made local to the buffer."
1218 ;; 1274 ;;
1219 ;; This function is called exclusively as an after-change function via 1275 ;; This function is called exclusively as an after-change function via
1220 ;; `c-before-font-lock-functions'. 1276 ;; `c-before-font-lock-functions'.
1221 (c-save-buffer-state 1277 (if (and c-multiline-string-start-char
1222 ((cll (progn (goto-char c-new-BEG) 1278 (not (c-characterp c-multiline-string-start-char)))
1223 (c-literal-limits))) 1279 ;; Only the last " might need to be marked.
1224 (beg-literal-type (and cll (c-literal-type cll))) 1280 (c-save-buffer-state
1225 (beg-limits 1281 ((beg-literal-limits
1226 (cond 1282 (progn (goto-char beg) (c-literal-limits)))
1227 ((and (eq beg-literal-type 'string) 1283 (beg-literal-type (c-literal-type beg-literal-limits))
1228 (c-unescaped-nls-in-string-p (car cll))) 1284 end-literal-limits end-literal-type)
1229 (cons 1285 (when (and (eq beg-literal-type 'string)
1230 (car cll) 1286 (c-get-char-property (car beg-literal-limits) 'syntax-table))
1287 (c-clear-char-property (car beg-literal-limits) 'syntax-table)
1288 (setq c-bc-changed-stringiness (not c-bc-changed-stringiness)))
1289 (setq end-literal-limits (progn (goto-char end) (c-literal-limits))
1290 end-literal-type (c-literal-type end-literal-limits))
1291 ;; Deal with the insertion of backslashes before a ".
1292 (goto-char end)
1293 (if (and (looking-at "\\\\*\"")
1294 (eq (logand (skip-chars-backward "\\\\" beg) 1) 1))
1295 (setq c-bc-changed-stringiness (not c-bc-changed-stringiness)))
1296 (when (eq (eq (eq beg-literal-type 'string)
1297 (eq end-literal-type 'string))
1298 c-bc-changed-stringiness)
1299 (c-multiline-string-check-final-quote)))
1300 ;; There could be several "s needing marking.
1301 (c-save-buffer-state
1302 ((cll (progn (goto-char c-new-BEG)
1303 (c-literal-limits)))
1304 (beg-literal-type (and cll (c-literal-type cll)))
1305 (beg-limits
1306 (cond
1307 ((and (eq beg-literal-type 'string)
1308 (c-unescaped-nls-in-string-p (car cll)))
1309 (cons
1310 (car cll)
1311 (progn
1312 (goto-char (1+ (car cll)))
1313 (search-forward-regexp
1314 (cdr (assq (char-after (car cll)) c-string-innards-re-alist))
1315 nil t)
1316 (min (1+ (point)) (point-max)))))
1317 ((and (null beg-literal-type)
1318 (goto-char beg)
1319 (eq (char-before) c-multiline-string-start-char)
1320 (memq (char-after) c-string-delims))
1321 (cons (point)
1322 (progn
1323 (forward-char)
1324 (search-forward-regexp
1325 (cdr (assq (char-before) c-string-innards-re-alist)) nil t)
1326 (1+ (point)))))
1327 (cll)))
1328 s)
1329 (goto-char
1330 (cond ((null beg-literal-type)
1331 c-new-BEG)
1332 ((eq beg-literal-type 'string)
1333 (car beg-limits))
1334 (t ; comment
1335 (cdr beg-limits))))
1336 (while
1337 (and
1338 (< (point) c-new-END)
1231 (progn 1339 (progn
1232 (goto-char (1+ (car cll))) 1340 ;; Skip over any comments before the next string.
1233 (search-forward-regexp 1341 (while (progn
1234 (cdr (assq (char-after (car cll)) c-string-innards-re-alist)) 1342 (setq s (parse-partial-sexp (point) c-new-END nil
1235 nil t) 1343 nil s 'syntax-table))
1236 (min (1+ (point)) (point-max))))) 1344 (and (not (nth 3 s))
1237 ((and (null beg-literal-type) 1345 (< (point) c-new-END)
1238 (goto-char beg) 1346 (not (memq (char-before) c-string-delims)))))
1239 (eq (char-before) c-multiline-string-start-char) 1347 ;; We're at the start of a string.
1240 (memq (char-after) c-string-delims)) 1348 (memq (char-before) c-string-delims)))
1241 (cons (point) 1349 (if (c-unescaped-nls-in-string-p (1- (point)))
1242 (progn 1350 (looking-at "\\(\\\\\\(.\\|\n|\\\r\\)\\|[^\"]\\)*")
1243 (forward-char) 1351 (looking-at (cdr (assq (char-before) c-string-innards-re-alist))))
1244 (search-forward-regexp 1352 (cond
1245 (cdr (assq (char-before) c-string-innards-re-alist)) nil t) 1353 ((memq (char-after (match-end 0)) '(?\n ?\r))
1246 (1+ (point))))) 1354 (c-put-char-property (1- (point)) 'syntax-table '(15))
1247 (cll))) 1355 (c-put-char-property (match-end 0) 'syntax-table '(15)))
1248 s) 1356 ((or (eq (match-end 0) (point-max))
1249 (goto-char 1357 (eq (char-after (match-end 0)) ?\\)) ; \ at EOB
1250 (cond ((null beg-literal-type) 1358 (c-put-char-property (1- (point)) 'syntax-table '(15))))
1251 c-new-BEG) 1359 (goto-char (min (1+ (match-end 0)) (point-max)))
1252 ((eq beg-literal-type 'string) 1360 (setq s nil)))))
1253 (car beg-limits))
1254 (t ; comment
1255 (cdr beg-limits))))
1256 (while
1257 (and
1258 (< (point) c-new-END)
1259 (progn
1260 ;; Skip over any comments before the next string.
1261 (while (progn
1262 (setq s (parse-partial-sexp (point) c-new-END nil
1263 nil s 'syntax-table))
1264 (and (not (nth 3 s))
1265 (< (point) c-new-END)
1266 (not (memq (char-before) c-string-delims)))))
1267 ;; We're at the start of a string.
1268 (memq (char-before) c-string-delims)))
1269 (if (c-unescaped-nls-in-string-p (1- (point)))
1270 (looking-at "[^\"]*")
1271 (looking-at (cdr (assq (char-before) c-string-innards-re-alist))))
1272 (cond
1273 ((memq (char-after (match-end 0)) '(?\n ?\r))
1274 (c-put-char-property (1- (point)) 'syntax-table '(15))
1275 (c-put-char-property (match-end 0) 'syntax-table '(15)))
1276 ((or (eq (match-end 0) (point-max))
1277 (eq (char-after (match-end 0)) ?\\)) ; \ at EOB
1278 (c-put-char-property (1- (point)) 'syntax-table '(15))))
1279 (goto-char (min (1+ (match-end 0)) (point-max)))
1280 (setq s nil))))
1281 1361
1282;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1362;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1283;; Parsing of quotes. 1363;; Parsing of quotes.