diff options
| author | Alan Mackenzie | 2017-07-01 15:43:07 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2017-07-01 15:43:07 +0000 |
| commit | 59d07875df9d44568d93a7517853e6a5ccaf1e5b (patch) | |
| tree | ec96cf9039ad80fefc6756aee7fbddc05b44ae13 | |
| parent | e620bbe38ed5e3e2a77f01eac2814c01dfa41c2d (diff) | |
| download | emacs-59d07875df9d44568d93a7517853e6a5ccaf1e5b.tar.gz emacs-59d07875df9d44568d93a7517853e6a5ccaf1e5b.zip | |
Make C++ digit separators work. Amend the handling of single quotes generally
Single quotes, even in strings and comments, are now marked with the
"punctuation" syntax-table property, except where they are validly bounding a
character literal. They are font locked with font-lock-warning-face except
where they are valid. This is done in C, C++, ObjC, and Java Modes.
* lisp/progmodes/cc-defs.el (c-clear-char-property-with-value-on-char-function)
(c-clear-char-property-with-value-on-char, c-put-char-properties-on-char): New
functions/macros.
* lisp/progmodes/cc-fonts.el (c-font-lock-invalid-single-quotes): New function.
(c-basic-matchers-before): invoke c-font-lock-invalid-single-quotes.
* lisp/progmodes/cc-langs.el (c-get-state-before-change-functions): Remove
c-before-after-change-digit-quote from wherever it occurs. Insert
c-parse-quotes-before-change into the entries for the languages where it is
needed.
(c-before-font-lock-functions): Remove c-before-after-change-digit-quote from
wherever it occurs. Insert c-parse-quotes-after-change into the entries for
the languages which need it.
(c-has-quoted-numbers): New lang-defconst/-defvar.
* lisp/progmodes/cc-mode.el (c-before-after-change-digit-quote): Remove.
(c-maybe-quoted-number-head, c-maybe-quoted-number-tail)
(c-maybe-quoted-number): New defconsts.
(c-quoted-number-head-before-point, c-quoted-number-tail-after-point)
(c-quoted-number-straddling-point, c-parse-quotes-before-change)
(c-parse-quotes-after-change): New functions.
| -rw-r--r-- | lisp/progmodes/cc-defs.el | 59 | ||||
| -rw-r--r-- | lisp/progmodes/cc-fonts.el | 33 | ||||
| -rw-r--r-- | lisp/progmodes/cc-langs.el | 22 | ||||
| -rw-r--r-- | lisp/progmodes/cc-mode.el | 294 |
4 files changed, 311 insertions, 97 deletions
diff --git a/lisp/progmodes/cc-defs.el b/lisp/progmodes/cc-defs.el index 377a981598a..85a4085e490 100644 --- a/lisp/progmodes/cc-defs.el +++ b/lisp/progmodes/cc-defs.el | |||
| @@ -1171,6 +1171,63 @@ been put there by c-put-char-property. POINT remains unchanged." | |||
| 1171 | nil ,from ,to ,value nil -property-)) | 1171 | nil ,from ,to ,value nil -property-)) |
| 1172 | ;; GNU Emacs | 1172 | ;; GNU Emacs |
| 1173 | `(c-clear-char-property-with-value-function ,from ,to ,property ,value))) | 1173 | `(c-clear-char-property-with-value-function ,from ,to ,property ,value))) |
| 1174 | |||
| 1175 | (defun c-clear-char-property-with-value-on-char-function (from to property | ||
| 1176 | value char) | ||
| 1177 | "Remove all text-properties PROPERTY with value VALUE on | ||
| 1178 | characters with value CHAR from the region [FROM, TO), as tested | ||
| 1179 | by `equal'. These properties are assumed to be over individual | ||
| 1180 | characters, having been put there by c-put-char-property. POINT | ||
| 1181 | remains unchanged." | ||
| 1182 | (let ((place from) | ||
| 1183 | ) | ||
| 1184 | (while ; loop round occurrences of (PROPERTY VALUE) | ||
| 1185 | (progn | ||
| 1186 | (while ; loop round changes in PROPERTY till we find VALUE | ||
| 1187 | (and | ||
| 1188 | (< place to) | ||
| 1189 | (not (equal (get-text-property place property) value))) | ||
| 1190 | (setq place (c-next-single-property-change place property nil to))) | ||
| 1191 | (< place to)) | ||
| 1192 | (if (eq (char-after place) char) | ||
| 1193 | (remove-text-properties place (1+ place) (cons property nil))) | ||
| 1194 | ;; Do we have to do anything with stickiness here? | ||
| 1195 | (setq place (1+ place))))) | ||
| 1196 | |||
| 1197 | (defmacro c-clear-char-property-with-value-on-char (from to property value char) | ||
| 1198 | "Remove all text-properties PROPERTY with value VALUE on | ||
| 1199 | characters with value CHAR from the region [FROM, TO), as tested | ||
| 1200 | by `equal'. These properties are assumed to be over individual | ||
| 1201 | characters, having been put there by c-put-char-property. POINT | ||
| 1202 | remains unchanged." | ||
| 1203 | (if c-use-extents | ||
| 1204 | ;; XEmacs | ||
| 1205 | `(let ((-property- ,property) | ||
| 1206 | (-char- ,char)) | ||
| 1207 | (map-extents (lambda (ext val) | ||
| 1208 | (if (and (equal (extent-property ext -property-) val) | ||
| 1209 | (eq (char-after | ||
| 1210 | (extent-start-position ext)) | ||
| 1211 | -char-)) | ||
| 1212 | (delete-extent ext))) | ||
| 1213 | nil ,from ,to ,value nil -property-)) | ||
| 1214 | ;; Gnu Emacs | ||
| 1215 | `(c-clear-char-property-with-value-on-char-function ,from ,to ,property | ||
| 1216 | ,value ,char))) | ||
| 1217 | |||
| 1218 | (defmacro c-put-char-properties-on-char (from to property value char) | ||
| 1219 | ;; This needs to be a macro because `property' passed to | ||
| 1220 | ;; `c-put-char-property' must be a constant. | ||
| 1221 | "Put the text property PROPERTY with value VALUE on characters | ||
| 1222 | with value CHAR in the region [FROM to)." | ||
| 1223 | `(let ((skip-string (concat "^" (list ,char))) | ||
| 1224 | (-to- ,to)) | ||
| 1225 | (save-excursion | ||
| 1226 | (goto-char ,from) | ||
| 1227 | (while (progn (skip-chars-forward skip-string -to-) | ||
| 1228 | (< (point) -to-)) | ||
| 1229 | (c-put-char-property (point) ,property ,value) | ||
| 1230 | (forward-char))))) | ||
| 1174 | 1231 | ||
| 1175 | ;; Macros to put overlays (Emacs) or extents (XEmacs) on buffer text. | 1232 | ;; Macros to put overlays (Emacs) or extents (XEmacs) on buffer text. |
| 1176 | ;; For our purposes, these are characterized by being possible to | 1233 | ;; For our purposes, these are characterized by being possible to |
| @@ -1228,6 +1285,8 @@ been put there by c-put-char-property. POINT remains unchanged." | |||
| 1228 | (def-edebug-spec c-put-char-property t) | 1285 | (def-edebug-spec c-put-char-property t) |
| 1229 | (def-edebug-spec c-get-char-property t) | 1286 | (def-edebug-spec c-get-char-property t) |
| 1230 | (def-edebug-spec c-clear-char-property t) | 1287 | (def-edebug-spec c-clear-char-property t) |
| 1288 | (def-edebug-spec c-clear-char-property-with-value-on-char t) | ||
| 1289 | (def-edebug-spec c-put-char-properties-on-char t) | ||
| 1231 | (def-edebug-spec c-clear-char-properties t) | 1290 | (def-edebug-spec c-clear-char-properties t) |
| 1232 | (def-edebug-spec c-put-overlay t) | 1291 | (def-edebug-spec c-put-overlay t) |
| 1233 | (def-edebug-spec c-delete-overlay t) | 1292 | (def-edebug-spec c-delete-overlay t) |
diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index 00812530357..66f2575f49f 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el | |||
| @@ -702,6 +702,36 @@ stuff. Used on level 1 and higher." | |||
| 702 | t) | 702 | t) |
| 703 | (c-put-font-lock-face start (1+ start) 'font-lock-warning-face))))) | 703 | (c-put-font-lock-face start (1+ start) 'font-lock-warning-face))))) |
| 704 | 704 | ||
| 705 | (defun c-font-lock-invalid-single-quotes (limit) | ||
| 706 | ;; This function will be called from font-lock for a region bounded by POINT | ||
| 707 | ;; and LIMIT, as though it were to identify a keyword for | ||
| 708 | ;; font-lock-keyword-face. It always returns NIL to inhibit this and | ||
| 709 | ;; prevent a repeat invocation. See elisp/lispref page "Search-based | ||
| 710 | ;; Fontification". | ||
| 711 | ;; | ||
| 712 | ;; This function fontifies invalid single quotes with | ||
| 713 | ;; `font-lock-warning-face'. These are the single quotes which | ||
| 714 | ;; o - aren't inside a literal; | ||
| 715 | ;; o - are marked with a syntax-table text property value '(1); and | ||
| 716 | ;; o - are NOT marked with a non-null c-digit-separator property. | ||
| 717 | (let ((limits (c-literal-limits)) | ||
| 718 | state beg end) | ||
| 719 | (if limits | ||
| 720 | (goto-char (cdr limits))) ; Even for being in a ' ' | ||
| 721 | (while (< (point) limit) | ||
| 722 | (setq beg (point)) | ||
| 723 | (setq state (parse-partial-sexp (point) limit nil nil nil 'syntax-table)) | ||
| 724 | (setq end (point)) | ||
| 725 | (goto-char beg) | ||
| 726 | (while (progn (skip-chars-forward "^'" end) | ||
| 727 | (< (point) end)) | ||
| 728 | (if (and (equal (c-get-char-property (point) 'syntax-table) '(1)) | ||
| 729 | (not (c-get-char-property (point) 'c-digit-separator))) | ||
| 730 | (c-put-font-lock-face (point) (1+ (point)) font-lock-warning-face)) | ||
| 731 | (forward-char)) | ||
| 732 | (parse-partial-sexp end limit nil nil state 'syntax-table))) | ||
| 733 | nil) | ||
| 734 | |||
| 705 | (c-lang-defconst c-basic-matchers-before | 735 | (c-lang-defconst c-basic-matchers-before |
| 706 | "Font lock matchers for basic keywords, labels, references and various | 736 | "Font lock matchers for basic keywords, labels, references and various |
| 707 | other easily recognizable things that should be fontified before generic | 737 | other easily recognizable things that should be fontified before generic |
| @@ -723,6 +753,9 @@ casts and declarations are fontified. Used on level 2 and higher." | |||
| 723 | (concat ".\\(" c-string-limit-regexp "\\)") | 753 | (concat ".\\(" c-string-limit-regexp "\\)") |
| 724 | '((c-font-lock-invalid-string))) | 754 | '((c-font-lock-invalid-string))) |
| 725 | 755 | ||
| 756 | ;; Invalid single quotes. | ||
| 757 | c-font-lock-invalid-single-quotes | ||
| 758 | |||
| 726 | ;; Fontify C++ raw strings. | 759 | ;; Fontify C++ raw strings. |
| 727 | ,@(when (c-major-mode-is 'c++-mode) | 760 | ,@(when (c-major-mode-is 'c++-mode) |
| 728 | '(c-font-lock-raw-strings)) | 761 | '(c-font-lock-raw-strings)) |
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 1ce0fbf7d05..8be806094cd 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el | |||
| @@ -474,18 +474,19 @@ so that all identifiers are recognized as words.") | |||
| 474 | ;; The value here may be a list of functions or a single function. | 474 | ;; The value here may be a list of functions or a single function. |
| 475 | t nil | 475 | t nil |
| 476 | c++ '(c-extend-region-for-CPP | 476 | c++ '(c-extend-region-for-CPP |
| 477 | ; c-before-after-change-extend-region-for-lambda-capture ; doesn't seem needed. | ||
| 478 | c-before-change-check-raw-strings | 477 | c-before-change-check-raw-strings |
| 479 | c-before-change-check-<>-operators | 478 | c-before-change-check-<>-operators |
| 480 | c-depropertize-CPP | 479 | c-depropertize-CPP |
| 481 | c-before-after-change-digit-quote | ||
| 482 | c-invalidate-macro-cache | 480 | c-invalidate-macro-cache |
| 483 | c-truncate-bs-cache) | 481 | c-truncate-bs-cache |
| 482 | c-parse-quotes-before-change) | ||
| 484 | (c objc) '(c-extend-region-for-CPP | 483 | (c objc) '(c-extend-region-for-CPP |
| 485 | c-depropertize-CPP | 484 | c-depropertize-CPP |
| 486 | c-invalidate-macro-cache | 485 | c-invalidate-macro-cache |
| 487 | c-truncate-bs-cache) | 486 | c-truncate-bs-cache |
| 488 | ;; java 'c-before-change-check-<>-operators | 487 | c-parse-quotes-before-change) |
| 488 | java 'c-parse-quotes-before-change | ||
| 489 | ;; 'c-before-change-check-<>-operators | ||
| 489 | awk 'c-awk-record-region-clear-NL) | 490 | awk 'c-awk-record-region-clear-NL) |
| 490 | (c-lang-defvar c-get-state-before-change-functions | 491 | (c-lang-defvar c-get-state-before-change-functions |
| 491 | (let ((fs (c-lang-const c-get-state-before-change-functions))) | 492 | (let ((fs (c-lang-const c-get-state-before-change-functions))) |
| @@ -515,18 +516,19 @@ parameters \(point-min) and \(point-max).") | |||
| 515 | t '(c-depropertize-new-text | 516 | t '(c-depropertize-new-text |
| 516 | c-change-expand-fl-region) | 517 | c-change-expand-fl-region) |
| 517 | (c objc) '(c-depropertize-new-text | 518 | (c objc) '(c-depropertize-new-text |
| 519 | c-parse-quotes-after-change | ||
| 518 | c-extend-font-lock-region-for-macros | 520 | c-extend-font-lock-region-for-macros |
| 519 | c-neutralize-syntax-in-and-mark-CPP | 521 | c-neutralize-syntax-in-and-mark-CPP |
| 520 | c-change-expand-fl-region) | 522 | c-change-expand-fl-region) |
| 521 | c++ '(c-depropertize-new-text | 523 | c++ '(c-depropertize-new-text |
| 524 | c-parse-quotes-after-change | ||
| 522 | c-extend-font-lock-region-for-macros | 525 | c-extend-font-lock-region-for-macros |
| 523 | ; c-before-after-change-extend-region-for-lambda-capture ; doesn't seem needed. | ||
| 524 | c-before-after-change-digit-quote | ||
| 525 | c-after-change-re-mark-raw-strings | 526 | c-after-change-re-mark-raw-strings |
| 526 | c-neutralize-syntax-in-and-mark-CPP | 527 | c-neutralize-syntax-in-and-mark-CPP |
| 527 | c-restore-<>-properties | 528 | c-restore-<>-properties |
| 528 | c-change-expand-fl-region) | 529 | c-change-expand-fl-region) |
| 529 | java '(c-depropertize-new-text | 530 | java '(c-depropertize-new-text |
| 531 | c-parse-quotes-after-change | ||
| 530 | c-restore-<>-properties | 532 | c-restore-<>-properties |
| 531 | c-change-expand-fl-region) | 533 | c-change-expand-fl-region) |
| 532 | awk '(c-depropertize-new-text | 534 | awk '(c-depropertize-new-text |
| @@ -609,6 +611,12 @@ EOL terminated statements." | |||
| 609 | (c c++ objc) t) | 611 | (c c++ objc) t) |
| 610 | (c-lang-defvar c-has-bitfields (c-lang-const c-has-bitfields)) | 612 | (c-lang-defvar c-has-bitfields (c-lang-const c-has-bitfields)) |
| 611 | 613 | ||
| 614 | (c-lang-defconst c-has-quoted-numbers | ||
| 615 | "Whether the language has numbers quoted like 4'294'967'295." | ||
| 616 | t nil | ||
| 617 | c++ t) | ||
| 618 | (c-lang-defvar c-has-quoted-numbers (c-lang-const c-has-quoted-numbers)) | ||
| 619 | |||
| 612 | (c-lang-defconst c-modified-constant | 620 | (c-lang-defconst c-modified-constant |
| 613 | "Regexp that matches a “modified” constant literal such as \"L\\='a\\='\", | 621 | "Regexp that matches a “modified” constant literal such as \"L\\='a\\='\", |
| 614 | a “long character”. In particular, this recognizes forms of constant | 622 | a “long character”. In particular, this recognizes forms of constant |
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index a501ebba256..c5ee60f7d79 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el | |||
| @@ -1083,101 +1083,215 @@ Note that the style variables are always made local to the buffer." | |||
| 1083 | (forward-line)) ; no infinite loop with, e.g., "#//" | 1083 | (forward-line)) ; no infinite loop with, e.g., "#//" |
| 1084 | ))))) | 1084 | ))))) |
| 1085 | 1085 | ||
| 1086 | (defun c-before-after-change-digit-quote (beg end &optional old-len) | 1086 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
| 1087 | ;; This function either removes or applies the punctuation value ('(1)) of | 1087 | ;; Parsing of quotes. |
| 1088 | ;; the `syntax-table' text property on single quote marks which are | 1088 | ;; |
| 1089 | ;; separator characters in long integer literals, e.g. "4'294'967'295". It | 1089 | ;; Valid digit separators in numbers will get the syntax-table "punctuation" |
| 1090 | ;; applies to both decimal/octal and hex literals. (FIXME (2016-06-10): it | 1090 | ;; property, '(1), and also the text property `c-digit-separator' value t. |
| 1091 | ;; should also apply to binary literals.) | 1091 | ;; |
| 1092 | ;; Invalid other quotes (i.e. those not validly bounding a single character, | ||
| 1093 | ;; or escaped character) will get the syntax-table "punctuation" property, | ||
| 1094 | ;; '(1), too. | ||
| 1095 | ;; | ||
| 1096 | ;; Note that, for convenience, these properties are applied even inside | ||
| 1097 | ;; comments and strings. | ||
| 1098 | |||
| 1099 | (defconst c-maybe-quoted-number-head | ||
| 1100 | (concat | ||
| 1101 | "\\(0\\(" | ||
| 1102 | "\\([Xx]\\([0-9a-fA-F]\\('[0-9a-fA-F]\\|[0-9a-fA-F]\\)*'?\\)?\\)" | ||
| 1103 | "\\|" | ||
| 1104 | "\\([Bb]\\([01]\\('[01]\\|[01]\\)*'?\\)?\\)" | ||
| 1105 | "\\|" | ||
| 1106 | "\\('[0-7]\\|[0-7]\\)*'?" | ||
| 1107 | "\\)" | ||
| 1108 | "\\|" | ||
| 1109 | "[1-9]\\('[0-9]\\|[0-9]\\)*'?" | ||
| 1110 | "\\)") | ||
| 1111 | "Regexp matching the head of a numeric literal, including with digit separators.") | ||
| 1112 | |||
| 1113 | (defun c-quoted-number-head-before-point () | ||
| 1114 | ;; Return non-nil when the head of a possibly quoted number is found | ||
| 1115 | ;; immediately before point. The value returned in this case is the buffer | ||
| 1116 | ;; position of the start of the head. | ||
| 1117 | (when c-has-quoted-numbers | ||
| 1118 | (save-excursion | ||
| 1119 | (let ((here (point)) | ||
| 1120 | ) | ||
| 1121 | (skip-chars-backward "0-9a-fA-F'") | ||
| 1122 | (if (and (memq (char-before) '(?x ?X)) | ||
| 1123 | (eq (char-before (1- (point))) ?0)) | ||
| 1124 | (backward-char 2)) | ||
| 1125 | (while (and (search-forward-regexp c-maybe-quoted-number-head here t) | ||
| 1126 | (< (match-end 0) here))) | ||
| 1127 | (and (eq (match-end 0) here) (match-beginning 0)))))) | ||
| 1128 | |||
| 1129 | (defconst c-maybe-quoted-number-tail | ||
| 1130 | (concat | ||
| 1131 | "\\(" | ||
| 1132 | "\\([xX']?[0-9a-fA-F]\\('[0-9a-fA-F]\\|[0-9a-fA-F]\\)*\\)" | ||
| 1133 | "\\|" | ||
| 1134 | "\\([bB']?[01]\\('[01]\\|[01]\\)*\\)" | ||
| 1135 | "\\|" | ||
| 1136 | "\\('?[0-9]\\('[0-9]\\|[0-9]\\)*\\)" | ||
| 1137 | "\\)") | ||
| 1138 | "Regexp matching the tail of a numeric literal, including with digit separators. | ||
| 1139 | Note that this is a strict tail, so won't match, e.g. \"0x....\".") | ||
| 1140 | |||
| 1141 | (defun c-quoted-number-tail-after-point () | ||
| 1142 | ;; Return non-nil when a proper tail of a possibly quoted number is found | ||
| 1143 | ;; immediately after point. The value returned in this case is the buffer | ||
| 1144 | ;; position of the end of the tail. | ||
| 1145 | (when c-has-quoted-numbers | ||
| 1146 | (and (looking-at c-maybe-quoted-number-tail) | ||
| 1147 | (match-end 0)))) | ||
| 1148 | |||
| 1149 | (defconst c-maybe-quoted-number | ||
| 1150 | (concat | ||
| 1151 | "\\(0\\(" | ||
| 1152 | "\\([Xx][0-9a-fA-F]\\('[0-9a-fA-F]\\|[0-9a-fA-F]\\)*\\)" | ||
| 1153 | "\\|" | ||
| 1154 | "\\([Bb][01]\\('[01]\\|[01]\\)*\\)" | ||
| 1155 | "\\|" | ||
| 1156 | "\\('[0-7]\\|[0-7]\\)*" | ||
| 1157 | "\\)" | ||
| 1158 | "\\|" | ||
| 1159 | "[1-9]\\('[0-9]\\|[0-9]\\)*" | ||
| 1160 | "\\)") | ||
| 1161 | "Regexp matching a numeric literal, including with digit separators.") | ||
| 1162 | |||
| 1163 | (defun c-quoted-number-straddling-point () | ||
| 1164 | ;; Return non-nil if a definitely quoted number starts before point and ends | ||
| 1165 | ;; after point. In this case the number is bounded by (match-beginning 0) | ||
| 1166 | ;; and (match-end 0). | ||
| 1167 | (when c-has-quoted-numbers | ||
| 1168 | (save-excursion | ||
| 1169 | (let ((here (point)) | ||
| 1170 | (bound (progn (skip-chars-forward "0-9a-fA-F'") (point)))) | ||
| 1171 | (goto-char here) | ||
| 1172 | (when (< (skip-chars-backward "0-9a-fA-F'") 0) | ||
| 1173 | (if (and (memq (char-before) '(?x ?X)) | ||
| 1174 | (eq (char-before (1- (point))) ?0)) | ||
| 1175 | (backward-char 2)) | ||
| 1176 | (while (and (search-forward-regexp c-maybe-quoted-number bound t) | ||
| 1177 | (<= (match-end 0) here))) | ||
| 1178 | (and (< (match-beginning 0) here) | ||
| 1179 | (> (match-end 0) here) | ||
| 1180 | (save-match-data | ||
| 1181 | (goto-char (match-beginning 0)) | ||
| 1182 | (save-excursion (search-forward "'" (match-end 0) t))))))))) | ||
| 1183 | |||
| 1184 | (defun c-parse-quotes-before-change (beg end) | ||
| 1185 | ;; This function analyzes 's near the region (c-new-BEG c-new-END), amending | ||
| 1186 | ;; those two variables as needed to include 's into that region when they | ||
| 1187 | ;; might be syntactically relevant to the change in progress. | ||
| 1092 | ;; | 1188 | ;; |
| 1093 | ;; In both uses of the function, the `syntax-table' properties are | 1189 | ;; Having amended that region, the function removes pertinent text |
| 1094 | ;; removed/applied only on quote marks which appear to be digit separators. | 1190 | ;; properties (syntax-table properties with value '(1) and c-digit-separator |
| 1191 | ;; props with value t) from 's in it. This operation is performed even | ||
| 1192 | ;; within strings and comments. | ||
| 1095 | ;; | 1193 | ;; |
| 1096 | ;; Point is undefined on both entry and exit to this function, and the | 1194 | ;; This function is called exclusively as a before-change function via the |
| 1097 | ;; return value has no significance. The function is called solely as a | 1195 | ;; variable `c-get-state-before-change-functions'. |
| 1098 | ;; before-change function (see `c-get-state-before-change-functions') and as | 1196 | (c-save-buffer-state (p-limit limits found) |
| 1099 | ;; an after change function (see `c-before-font-lock-functions', with the | 1197 | ;; Special consideraton for deleting \ from '\''. |
| 1100 | ;; parameters BEG, END, and (optionally) OLD-LEN being given the standard | 1198 | (if (and (> end beg) |
| 1101 | ;; values for before/after-change functions. | 1199 | (eq (char-before end) ?\\) |
| 1102 | (c-save-buffer-state ((num-begin c-new-BEG) digit-re try-end) | 1200 | (<= c-new-END end)) |
| 1201 | (setq c-new-END (min (1+ end) (point-max)))) | ||
| 1202 | |||
| 1203 | ;; Do we have a ' (or something like ',',',',',') within range of | ||
| 1204 | ;; c-new-BEG? | ||
| 1205 | (goto-char c-new-BEG) | ||
| 1206 | (setq p-limit (max (- (point) 2) (point-min))) | ||
| 1207 | (while (and (skip-chars-backward "^\\\\'" p-limit) | ||
| 1208 | (> (point) p-limit)) | ||
| 1209 | (when (eq (char-before) ?\\) | ||
| 1210 | (setq p-limit (max (1- p-limit) (point-min)))) | ||
| 1211 | (backward-char) | ||
| 1212 | (setq c-new-BEG (point))) | ||
| 1213 | (beginning-of-line) | ||
| 1214 | (while (and | ||
| 1215 | (setq found (search-forward-regexp "\\('\\([^'\\]\\|\\\\.\\)\\)*'" | ||
| 1216 | c-new-BEG 'limit)) | ||
| 1217 | (< (point) (1- c-new-BEG)))) | ||
| 1218 | (if found | ||
| 1219 | (setq c-new-BEG | ||
| 1220 | (if (and (eq (point) (1- c-new-BEG)) | ||
| 1221 | (eq (char-after) ?')) ; "''" before c-new-BEG. | ||
| 1222 | (1- c-new-BEG) | ||
| 1223 | (match-beginning 0)))) | ||
| 1224 | |||
| 1225 | ;; Check for a number with quote separators straddling c-new-BEG | ||
| 1226 | (when c-has-quoted-numbers | ||
| 1227 | (goto-char c-new-BEG) | ||
| 1228 | (when ;; (c-quoted-number-straddling-point) | ||
| 1229 | (c-quoted-number-head-before-point) | ||
| 1230 | (setq c-new-BEG (match-beginning 0)))) | ||
| 1231 | |||
| 1232 | ;; Do we have a ' (or something like ',',',',...,',') within range of | ||
| 1233 | ;; c-new-END? | ||
| 1103 | (goto-char c-new-END) | 1234 | (goto-char c-new-END) |
| 1104 | (when (looking-at "\\(x\\)?[0-9a-fA-F']+") | 1235 | (setq p-limit (min (+ (point) 2) (point-max))) |
| 1105 | (setq c-new-END (match-end 0))) | 1236 | (while (and (skip-chars-forward "^\\\\'" p-limit) |
| 1237 | (< (point) p-limit)) | ||
| 1238 | (when (eq (char-after) ?\\) | ||
| 1239 | (setq p-limit (min (1+ p-limit) (point-max)))) | ||
| 1240 | (forward-char) | ||
| 1241 | (setq c-new-END (point))) | ||
| 1242 | (if (looking-at "[^']?\\('\\([^'\\]\\|\\\\.\\)\\)*'") | ||
| 1243 | (setq c-new-END (match-end 0))) | ||
| 1244 | |||
| 1245 | ;; Check for a number with quote separators straddling c-new-END. | ||
| 1246 | (when c-has-quoted-numbers | ||
| 1247 | (goto-char c-new-END) | ||
| 1248 | (when ;; (c-quoted-number-straddling-point) | ||
| 1249 | (c-quoted-number-tail-after-point) | ||
| 1250 | (setq c-new-END (match-end 0)))) | ||
| 1251 | |||
| 1252 | ;; Remove the '(1) syntax-table property from all "'"s within (c-new-BEG | ||
| 1253 | ;; c-new-END). | ||
| 1254 | (c-clear-char-property-with-value-on-char | ||
| 1255 | c-new-BEG c-new-END | ||
| 1256 | 'syntax-table '(1) | ||
| 1257 | ?') | ||
| 1258 | ;; Remove the c-digit-separator text property from the same "'"s. | ||
| 1259 | (when c-has-quoted-numbers | ||
| 1260 | (c-clear-char-property-with-value-on-char | ||
| 1261 | c-new-BEG c-new-END | ||
| 1262 | 'c-digit-separator t | ||
| 1263 | ?')))) | ||
| 1264 | |||
| 1265 | (defun c-parse-quotes-after-change (beg end old-len) | ||
| 1266 | ;; This function applies syntax-table properties (value '(1)) and | ||
| 1267 | ;; c-digit-separator properties as needed to 's within the range (c-new-BEG | ||
| 1268 | ;; c-new-END). This operation is performed even within strings and | ||
| 1269 | ;; comments. | ||
| 1270 | ;; | ||
| 1271 | ;; This function is called exclusively as an after-change function via the | ||
| 1272 | ;; variable `c-before-font-lock-functions'. | ||
| 1273 | (c-save-buffer-state (p-limit limits num-beg num-end clear-from-BEG-to) | ||
| 1274 | ;; Apply the needed syntax-table and c-digit-separator text properties to | ||
| 1275 | ;; quotes. | ||
| 1106 | (goto-char c-new-BEG) | 1276 | (goto-char c-new-BEG) |
| 1107 | (when (looking-at "\\(x?\\)[0-9a-fA-F']") | 1277 | (while (and (< (point) c-new-END) |
| 1108 | (if (re-search-backward "\\(0x\\)?[0-9a-fA-F]*\\=" nil t) | 1278 | (search-forward "'" c-new-END 'limit)) |
| 1109 | (setq c-new-BEG (point)))) | 1279 | (cond ((and (eq (char-before (1- (point))) ?\\) |
| 1110 | 1280 | ;; Check we've got an odd number of \s, here. | |
| 1111 | (while | ||
| 1112 | (re-search-forward "[0-9a-fA-F]'[0-9a-fA-F]" c-new-END t) | ||
| 1113 | (setq try-end (1- (point))) | ||
| 1114 | (re-search-backward "[^0-9a-fA-F']" num-begin t) | ||
| 1115 | (setq digit-re | ||
| 1116 | (cond | ||
| 1117 | ((and (not (bobp)) (eq (char-before) ?0) (memq (char-after) '(?x ?X))) | ||
| 1118 | "[0-9a-fA-F]") | ||
| 1119 | ((and (eq (char-after (1+ (point))) ?0) | ||
| 1120 | (memq (char-after (+ 2 (point))) '(?b ?B))) | ||
| 1121 | "[01]") | ||
| 1122 | ((memq (char-after (1+ (point))) '(?0 ?1 ?2 ?3 ?4 ?5 ?6 ?7 ?8 ?9)) | ||
| 1123 | "[0-9]") | ||
| 1124 | (t nil))) | ||
| 1125 | (when digit-re | ||
| 1126 | (cond ((eq (char-after) ?x) (forward-char)) | ||
| 1127 | ((looking-at ".?0[Bb]") (goto-char (match-end 0))) | ||
| 1128 | ((looking-at digit-re)) | ||
| 1129 | (t (forward-char))) | ||
| 1130 | (when (not (c-in-literal)) | ||
| 1131 | (let ((num-end ; End of valid sequence of digits/quotes. | ||
| 1132 | (save-excursion | ||
| 1133 | (re-search-forward | ||
| 1134 | (concat "\\=\\(" digit-re "+'\\)*" digit-re "+") nil t) | ||
| 1135 | (point)))) | ||
| 1136 | (setq try-end ; End of sequence of digits/quotes | ||
| 1137 | (save-excursion | 1281 | (save-excursion |
| 1138 | (re-search-forward | 1282 | (backward-char) |
| 1139 | (concat "\\=\\(" digit-re "\\|'\\)+") nil t) | 1283 | (eq (logand (skip-chars-backward "\\\\") 1) 1)))) ; not a real '. |
| 1140 | (point))) | 1284 | ((c-quoted-number-straddling-point) |
| 1141 | (while (re-search-forward | 1285 | (setq num-beg (match-beginning 0) |
| 1142 | (concat digit-re "\\('\\)" digit-re) num-end t) | 1286 | num-end (match-end 0)) |
| 1143 | (if old-len ; i.e. are we in an after-change function? | 1287 | (c-put-char-properties-on-char num-beg num-end |
| 1144 | (c-put-char-property (match-beginning 1) 'syntax-table '(1)) | 1288 | 'syntax-table '(1) ?') |
| 1145 | (c-clear-char-property (match-beginning 1) 'syntax-table)) | 1289 | (c-put-char-properties-on-char num-beg num-end |
| 1146 | (backward-char))))) | 1290 | 'c-digit-separator t ?') |
| 1147 | (goto-char try-end) | 1291 | (goto-char num-end)) |
| 1148 | (setq num-begin (point))))) | 1292 | ((looking-at "\\([^\\']\\|\\\\.\\)'") ; balanced quoted expression. |
| 1149 | 1293 | (goto-char (match-end 0))) | |
| 1150 | ;; The following doesn't seem needed at the moment (2016-08-15). | 1294 | (t (c-put-char-property (1- (point)) 'syntax-table '(1))))))) |
| 1151 | ;; (defun c-before-after-change-extend-region-for-lambda-capture | ||
| 1152 | ;; (_beg _end &optional _old-len) | ||
| 1153 | ;; ;; In C++ Mode, extend the region (c-new-BEG c-new-END) to cover any lambda | ||
| 1154 | ;; ;; function capture lists we happen to be inside. This function is expected | ||
| 1155 | ;; ;; to be called both as a before-change and after change function. | ||
| 1156 | ;; ;; | ||
| 1157 | ;; ;; Note that these things _might_ be nested, with a capture list looking | ||
| 1158 | ;; ;; like: | ||
| 1159 | ;; ;; | ||
| 1160 | ;; ;; [ ...., &foo = [..](){...}(..), ... ] | ||
| 1161 | ;; ;; | ||
| 1162 | ;; ;; . What a wonderful language is C++. ;-) | ||
| 1163 | ;; (c-save-buffer-state (paren-state pos) | ||
| 1164 | ;; (goto-char c-new-BEG) | ||
| 1165 | ;; (setq paren-state (c-parse-state)) | ||
| 1166 | ;; (while (setq pos (c-pull-open-brace paren-state)) | ||
| 1167 | ;; (goto-char pos) | ||
| 1168 | ;; (when (c-looking-at-c++-lambda-capture-list) | ||
| 1169 | ;; (setq c-new-BEG (min c-new-BEG pos)) | ||
| 1170 | ;; (if (c-go-list-forward) | ||
| 1171 | ;; (setq c-new-END (max c-new-END (point)))))) | ||
| 1172 | |||
| 1173 | ;; (goto-char c-new-END) | ||
| 1174 | ;; (setq paren-state (c-parse-state)) | ||
| 1175 | ;; (while (setq pos (c-pull-open-brace paren-state)) | ||
| 1176 | ;; (goto-char pos) | ||
| 1177 | ;; (when (c-looking-at-c++-lambda-capture-list) | ||
| 1178 | ;; (setq c-new-BEG (min c-new-BEG pos)) | ||
| 1179 | ;; (if (c-go-list-forward) | ||
| 1180 | ;; (setq c-new-END (max c-new-END (point)))))))) | ||
| 1181 | 1295 | ||
| 1182 | (defun c-before-change (beg end) | 1296 | (defun c-before-change (beg end) |
| 1183 | ;; Function to be put on `before-change-functions'. Primarily, this calls | 1297 | ;; Function to be put on `before-change-functions'. Primarily, this calls |