mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-02-27 18:30:47 -08:00
CC Mode: Enhance C++ Mode raw strings to multi-line strings for any language
* lisp/progmodes/cc-defs.el (cadar, caddr, cdddr): Add defsubsts for these for when they are missing from the host Emacs. (c-point): Add new `position' 'boll "beginning of logical line". (c-clear-char-properties): Return the position of the lowest removed property. * lisp/progmodes/cc-engine.el (c-full-pp-to-literal): Fix for rare case where LIMIT < START in parse-partial-sexp. (c-old-beg-rs, c-old-end-rs, c-raw-string-end-delim-disrupted) (c-raw-string-pos, c-raw-string-in-end-delim, c-depropertize-raw-string) (c-depropertize-raw-strings-in-region, c-before-change-check-raw-strings) (c-propertize-raw-string-id, c-propertize-raw-string-opener): Old functions and variables removed or renamed "raw" -> "ml" and adapted. (c-old-beg-ml, c-old-1-beg-ml, c-old-end-ml, c-beg-pos, c-end-pos) (c-ml-string-end-delim-disrupted, c-depropertize-ml-string-delims) (c-ml-string-delims-around-point,c-position-wrt-ml-delims) (c-before-change-check-ml-strings, c-after-change-unmark-ml-strings) (c-maybe-re-mark-ml-string, c-propertize-ml-string-id) (c-propertize-ml-string-opener, c-depropertize-ml-string) (c-depropertize-ml-strings-in-region): New functions and variables adapted and possibly renamed from "raw" -> "ml". (c-ml-string-make-closer-re, c-ml-string-make-opener-re) (c-c++-make-ml-string-closer-re, c-c++-make-ml-string-opener-re) (c-get-ml-closer, c-ml-string-opener-around-point) (c-ml-string-opener-intersects-region, c-ml-string-opener-at-or-around-point) (c-ml-string-back-to-neutral, c-ml-string-in-end-delim, c-neutralize-pos) (c-neutralized-prop): New functions and variables. * lisp/progmodes/cc-fonts.el (c-basic-matchers-before): Replace c-font-lock-raw-strings with c-font-lock-ml-strings. (c-font-lock-ml-strings): New function taking the place of the old c-font-lock-ml-strings. * lisp/progmodes/cc-langs.el (c-get-state-before-change-functions): Move c-depropertize-CPP to the second item of the C++ entry, and replace c-before-change-check-raw-strings by c-before-change-check-ml-strings. Add a new entry for Pike Mode. (c-before-font-lock-functions): (Replace c-after-change-unmark-raw-strings by c-after-change-unmark-ml-strings in the C++ entry, and add a new entry for Pike Mode. (c-ml-string-backslash-escapes, c-ml-string-non-punc-skip-chars) (c-ml-string-opener-re, c-ml-string-max-opener-len, c-ml-string-any-closer-re) (c-ml-string-max-closer-len, c-ml-string-max-closer-len-no-leader) (c-ml-string-back-closer-re, c-make-ml-string-closer-re-function) (c-make-ml-string-opener-re-function, c-ml-string-cpp-or-opener-re) (c-cpp-or-ml-match-offset): New c-lang-defconsts and c-land-defvars. (c-multiline-string-start-char): Remove the Pike Mode setting. * lisp/progmodes/cc-mode.el (c-depropertize-CPP): Test for general ml strings rather than C++ raw strings. (c-unescaped-nls-in-string-p): Handle languages with ml strings. (c-clear-string-fences): Fix bug with wrong parenthesisation. (c-before-change-check-unbalanced-strings) (c-after-change-mark-abnormal-strings, c-after-change-escape-NL-in-string): Adapt for multi-line strings.
This commit is contained in:
parent
5d50acd0a6
commit
c4d34d24e3
5 changed files with 1189 additions and 574 deletions
|
|
@ -174,6 +174,10 @@ This variant works around bugs in `eval-when-compile' in various
|
|||
|
||||
|
||||
;;; Macros.
|
||||
(or (fboundp 'cadar) (defsubst cadar (elt) (car (cdar elt))))
|
||||
(or (fboundp 'caddr) (defsubst caddr (elt) (car (cddr elt))))
|
||||
(or (fboundp 'cdddr) (defsubst cdddr (elt) (cdr (cddr elt))))
|
||||
|
||||
(defmacro c--mapcan (fun liszt)
|
||||
;; CC Mode equivalent of `mapcan' which bridges the difference
|
||||
;; between the host [X]Emacsen."
|
||||
|
|
@ -236,6 +240,7 @@ The current point is used if POINT isn't specified. POSITION can be
|
|||
one of the following symbols:
|
||||
|
||||
`bol' -- beginning of line
|
||||
`boll' -- beginning of logical line (i.e. without preceding escaped NL)
|
||||
`eol' -- end of line
|
||||
`eoll' -- end of logical line (i.e. without escaped NL)
|
||||
`bod' -- beginning of defun
|
||||
|
|
@ -266,6 +271,15 @@ to it is returned. This function does not modify the point or the mark."
|
|||
(beginning-of-line)
|
||||
(point))))
|
||||
|
||||
((eq position 'boll)
|
||||
`(save-excursion
|
||||
,@(if point `((goto-char ,point)))
|
||||
(while (progn (beginning-of-line)
|
||||
(when (not (bobp))
|
||||
(eq (char-before (1- (point))) ?\\)))
|
||||
(backward-char))
|
||||
(point)))
|
||||
|
||||
((eq position 'eol)
|
||||
(if (and (cc-bytecomp-fboundp 'line-end-position) (not point))
|
||||
'(line-end-position)
|
||||
|
|
@ -1254,6 +1268,9 @@ MODE is either a mode symbol or a list of mode symbols."
|
|||
;; region that has been put with `c-put-char-property'. PROPERTY is
|
||||
;; assumed to be constant.
|
||||
;;
|
||||
;; The returned value is the buffer position of the lowest character
|
||||
;; whose PROPERTY was removed, or nil if there was none.
|
||||
;;
|
||||
;; Note that this function does not clean up the property from the
|
||||
;; lists of the `rear-nonsticky' properties in the region, if such
|
||||
;; are used. Thus it should not be used for common properties like
|
||||
|
|
@ -1262,20 +1279,28 @@ MODE is either a mode symbol or a list of mode symbols."
|
|||
;; This macro does hidden buffer changes.
|
||||
(declare (debug t))
|
||||
(setq property (eval property))
|
||||
(if c-use-extents
|
||||
;; XEmacs.
|
||||
`(map-extents (lambda (ext ignored)
|
||||
(delete-extent ext))
|
||||
nil ,from ,to nil nil ',property)
|
||||
;; Emacs.
|
||||
(if (and (fboundp 'syntax-ppss)
|
||||
(eq `,property 'syntax-table))
|
||||
`(let ((-from- ,from) (-to- ,to))
|
||||
(setq c-syntax-table-hwm
|
||||
(min c-syntax-table-hwm
|
||||
(c-min-property-position -from- -to- ',property)))
|
||||
(remove-text-properties -from- -to- '(,property nil)))
|
||||
`(remove-text-properties ,from ,to '(,property nil)))))
|
||||
`(let* ((-to- ,to)
|
||||
(ret (c-min-property-position ,from -to- ',property)))
|
||||
(if (< ret -to-)
|
||||
(progn
|
||||
,(cond
|
||||
(c-use-extents
|
||||
;; XEmacs
|
||||
`(map-extents (lambda (ext ignored)
|
||||
(delete-extent ext))
|
||||
nil ret -to- nil nil ',property))
|
||||
((and (fboundp 'syntax-ppss)
|
||||
(eq property 'syntax-table))
|
||||
;; Emacs 'syntax-table
|
||||
`(progn
|
||||
(setq c-syntax-table-hwm
|
||||
(min c-syntax-table-hwm ret))
|
||||
(remove-text-properties ret -to- '(,property nil))))
|
||||
(t
|
||||
;; Emacs other property.
|
||||
`(remove-text-properties ret -to- '(,property nil))))
|
||||
ret)
|
||||
nil)))
|
||||
|
||||
(defmacro c-clear-syn-tab-properties (from to)
|
||||
;; Remove all occurrences of the `syntax-table' and `c-fl-syn-tab' text
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -781,9 +781,9 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
;; Invalid single quotes.
|
||||
c-font-lock-invalid-single-quotes
|
||||
|
||||
;; Fontify C++ raw strings.
|
||||
,@(when (c-major-mode-is 'c++-mode)
|
||||
'(c-font-lock-raw-strings))
|
||||
;; Fontify multiline strings.
|
||||
,@(when (c-lang-const c-ml-string-opener-re)
|
||||
'(c-font-lock-ml-strings))
|
||||
|
||||
;; Fontify keyword constants.
|
||||
,@(when (c-lang-const c-constant-kwds)
|
||||
|
|
@ -1737,8 +1737,8 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
(c-font-lock-declarators limit t in-typedef
|
||||
(not (c-bs-at-toplevel-p (point)))))))))))
|
||||
|
||||
(defun c-font-lock-raw-strings (limit)
|
||||
;; Fontify C++ raw strings.
|
||||
(defun c-font-lock-ml-strings (limit)
|
||||
;; Fontify multi-line strings.
|
||||
;;
|
||||
;; This function will be called from font-lock for a region bounded by POINT
|
||||
;; and LIMIT, as though it were to identify a keyword for
|
||||
|
|
@ -1748,52 +1748,75 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
(let* ((state (c-semi-pp-to-literal (point)))
|
||||
(string-start (and (eq (cadr state) 'string)
|
||||
(car (cddr state))))
|
||||
(raw-id (and string-start
|
||||
(c-at-c++-raw-string-opener string-start)
|
||||
(match-string-no-properties 1)))
|
||||
(content-start (and raw-id (point))))
|
||||
(open-delim (and string-start
|
||||
(save-excursion
|
||||
(goto-char (1+ string-start))
|
||||
(c-ml-string-opener-around-point))))
|
||||
(string-delims (and open-delim
|
||||
(cons open-delim (c-get-ml-closer open-delim))))
|
||||
found)
|
||||
;; We go round the next loop twice per raw string, once for each "end".
|
||||
(while (< (point) limit)
|
||||
(if raw-id
|
||||
;; Search for the raw string end delimiter
|
||||
(progn
|
||||
(when (search-forward-regexp (concat ")\\(" (regexp-quote raw-id) "\\)\"")
|
||||
limit 'limit)
|
||||
(c-put-font-lock-face content-start (match-beginning 1)
|
||||
'font-lock-string-face)
|
||||
(c-remove-font-lock-face (match-beginning 1) (point)))
|
||||
(setq raw-id nil))
|
||||
;; Search for the start of a raw string.
|
||||
(when (search-forward-regexp
|
||||
"R\\(\"\\)\\([^ ()\\\n\r\t]\\{0,16\\}\\)(" limit 'limit)
|
||||
(when
|
||||
;; Make sure we're not in a comment or string.
|
||||
(and
|
||||
(not (memq (c-get-char-property (match-beginning 0) 'face)
|
||||
'(font-lock-comment-face font-lock-comment-delimiter-face
|
||||
font-lock-string-face)))
|
||||
(or (and (eobp)
|
||||
(eq (c-get-char-property (1- (point)) 'face)
|
||||
'font-lock-warning-face))
|
||||
(not (eq (c-get-char-property (point) 'face) 'font-lock-comment-face))
|
||||
;; (eq (c-get-char-property (point) 'face) 'font-lock-string-face)
|
||||
(and (equal (c-get-char-property (match-end 2) 'syntax-table) '(1))
|
||||
(equal (c-get-char-property (match-beginning 1) 'syntax-table)
|
||||
'(1)))))
|
||||
(let ((paren-prop (c-get-char-property (1- (point)) 'syntax-table)))
|
||||
(if paren-prop
|
||||
(progn
|
||||
(c-put-font-lock-face (match-beginning 0) (match-end 0)
|
||||
'font-lock-warning-face)
|
||||
(when
|
||||
(and
|
||||
(equal paren-prop '(15))
|
||||
(not (c-search-forward-char-property 'syntax-table '(15) limit)))
|
||||
(goto-char limit)))
|
||||
(c-remove-font-lock-face (match-beginning 0) (match-end 2))
|
||||
(setq raw-id (match-string-no-properties 2))
|
||||
(setq content-start (match-end 0)))))))))
|
||||
nil)
|
||||
(cond
|
||||
;; Point is not in an ml string
|
||||
((not string-delims)
|
||||
(while (and (setq found (re-search-forward c-ml-string-opener-re
|
||||
limit 'limit))
|
||||
(> (match-beginning 0) (point-min))
|
||||
(memq (c-get-char-property (1- (match-beginning 0)) 'face)
|
||||
'(font-lock-comment-face font-lock-string-face
|
||||
font-lock-comment-delimiter-face))))
|
||||
(when found
|
||||
(setq open-delim (cons (match-beginning 1)
|
||||
(cons (match-end 1) (match-beginning 2)))
|
||||
string-delims (cons open-delim (c-get-ml-closer open-delim)))
|
||||
(goto-char (caar string-delims))))
|
||||
|
||||
;; Point is in the body of an ml string.
|
||||
((and string-delims
|
||||
(>= (point) (cadar string-delims))
|
||||
(or (not (cdr string-delims))
|
||||
(< (point) (cadr string-delims))))
|
||||
(if (cdr string-delims)
|
||||
(goto-char (cadr string-delims))
|
||||
(if (equal (c-get-char-property (1- (cadar string-delims))
|
||||
'syntax-table)
|
||||
'(15)) ; "Always" the case.
|
||||
;; The next search should be successful for an unterminated ml
|
||||
;; string inside a macro, but not for any other unterminated
|
||||
;; string.
|
||||
(progn
|
||||
(or (c-search-forward-char-property 'syntax-table '(15) limit)
|
||||
(goto-char limit))
|
||||
(setq string-delims nil))
|
||||
(c-benign-error "Missing '(15) syntax-table property at %d"
|
||||
(1- (cadar string-delims)))
|
||||
(setq string-delims nil))))
|
||||
|
||||
;; Point is at or in a closing delimiter
|
||||
((and string-delims
|
||||
(cdr string-delims)
|
||||
(>= (point) (cadr string-delims)))
|
||||
(c-put-font-lock-face (cadr string-delims) (1+ (cadr string-delims))
|
||||
'font-lock-string-face)
|
||||
(c-remove-font-lock-face (1+ (cadr string-delims))
|
||||
(caddr string-delims))
|
||||
(goto-char (caddr string-delims))
|
||||
(setq string-delims nil))
|
||||
|
||||
;; point is at or in an opening delimiter.
|
||||
(t
|
||||
(if (cdr string-delims)
|
||||
(progn
|
||||
(c-remove-font-lock-face (caar string-delims)
|
||||
(1- (cadar string-delims)))
|
||||
(c-put-font-lock-face (1- (cadar string-delims))
|
||||
(cadar string-delims)
|
||||
'font-lock-string-face))
|
||||
(c-put-font-lock-face (caar string-delims) (cadar string-delims)
|
||||
'font-lock-warning-face))
|
||||
(goto-char (cadar string-delims)))))
|
||||
nil))
|
||||
|
||||
(defun c-font-lock-c++-lambda-captures (limit)
|
||||
;; Fontify the lambda capture component of C++ lambda declarations.
|
||||
|
|
|
|||
|
|
@ -453,9 +453,9 @@ so that all identifiers are recognized as words.")
|
|||
;; The value here may be a list of functions or a single function.
|
||||
t 'c-before-change-check-unbalanced-strings
|
||||
c++ '(c-extend-region-for-CPP
|
||||
c-before-change-check-raw-strings
|
||||
c-before-change-check-<>-operators
|
||||
c-depropertize-CPP
|
||||
c-before-change-check-ml-strings
|
||||
c-before-change-check-<>-operators
|
||||
c-truncate-bs-cache
|
||||
c-before-change-check-unbalanced-strings
|
||||
c-parse-quotes-before-change)
|
||||
|
|
@ -467,6 +467,8 @@ so that all identifiers are recognized as words.")
|
|||
java '(c-parse-quotes-before-change
|
||||
c-before-change-check-unbalanced-strings
|
||||
c-before-change-check-<>-operators)
|
||||
pike '(c-before-change-check-ml-strings
|
||||
c-before-change-check-unbalanced-strings)
|
||||
awk 'c-awk-record-region-clear-NL)
|
||||
(c-lang-defvar c-get-state-before-change-functions
|
||||
(let ((fs (c-lang-const c-get-state-before-change-functions)))
|
||||
|
|
@ -506,7 +508,7 @@ parameters \(point-min) and \(point-max).")
|
|||
c-change-expand-fl-region)
|
||||
c++ '(c-depropertize-new-text
|
||||
c-after-change-escape-NL-in-string
|
||||
c-after-change-unmark-raw-strings
|
||||
c-after-change-unmark-ml-strings
|
||||
c-parse-quotes-after-change
|
||||
c-after-change-mark-abnormal-strings
|
||||
c-extend-font-lock-region-for-macros
|
||||
|
|
@ -519,6 +521,11 @@ parameters \(point-min) and \(point-max).")
|
|||
c-after-change-mark-abnormal-strings
|
||||
c-restore-<>-properties
|
||||
c-change-expand-fl-region)
|
||||
pike '(c-depropertize-new-text
|
||||
c-after-change-escape-NL-in-string
|
||||
c-after-change-unmark-ml-strings
|
||||
c-after-change-mark-abnormal-strings
|
||||
c-change-expand-fl-region)
|
||||
awk '(c-depropertize-new-text
|
||||
c-awk-extend-and-syntax-tablify-region))
|
||||
(c-lang-defvar c-before-font-lock-functions
|
||||
|
|
@ -620,6 +627,176 @@ Note that to set up a language to use this, additionally:
|
|||
'(?\")))
|
||||
(c-lang-defvar c-string-delims (c-lang-const c-string-delims))
|
||||
|
||||
|
||||
;; The next section of the code defines multi-line ("ml") strings for each
|
||||
;; language. By default, there are no ml strings in a language. To configure
|
||||
;; them, set each needed lang const in the section. See further details in
|
||||
;; cc-engine.el (search for "Handling of CC Mode multi-line strings.").
|
||||
(c-lang-defconst c-ml-string-backslash-escapes
|
||||
;; N.B. if `c-ml-string-backslash-escapes' is non-nil, you probably need a
|
||||
;; `c-ml-string-any-closer-re' that scans backslashed characters, etc.
|
||||
"If non-nil, a \\ character escapes the next character in a ml string.
|
||||
Otherwise such a \\ will be marked to be handled as any other character."
|
||||
t nil
|
||||
pike t
|
||||
)
|
||||
|
||||
(c-lang-defconst c-ml-string-non-punc-skip-chars
|
||||
;; A `skip-chars-forward' argument which skips over all ml string characters
|
||||
;; which don't need to be marked with punctuation ('(1)) syntax.
|
||||
t (if (c-lang-const c-ml-string-backslash-escapes)
|
||||
"^\""
|
||||
"^\"\\"))
|
||||
(c-lang-defvar c-ml-string-non-punc-skip-chars
|
||||
(c-lang-const c-ml-string-non-punc-skip-chars))
|
||||
|
||||
(c-lang-defconst c-ml-string-opener-re
|
||||
"If non-nil, a regexp that matches a multi-line string opener.
|
||||
It may also match context.
|
||||
|
||||
Such an opener must be at least 2 characters long, and must
|
||||
contain a \" character. (match-string 1) matches the actual
|
||||
delimiter and (match-string 2) matches the actual \". If a
|
||||
delimiter contains several \"s, it is recommended to configure
|
||||
the first of them as \"the\" \"."
|
||||
t nil
|
||||
pike "\\(#\\(\"\\)\\)"
|
||||
c++ "\\(R\\(\"\\)[^ ()\\\n\r\t]\\{0,16\\}(\\)")
|
||||
(c-lang-defvar c-ml-string-opener-re (c-lang-const c-ml-string-opener-re))
|
||||
|
||||
(c-lang-defconst c-ml-string-max-opener-len
|
||||
"If non-nil, the maximum length of a multi-line string opener."
|
||||
t nil
|
||||
pike 2
|
||||
c++ 19)
|
||||
(c-lang-defvar c-ml-string-max-opener-len
|
||||
(c-lang-const c-ml-string-max-opener-len))
|
||||
|
||||
(c-lang-defconst c-ml-string-any-closer-re
|
||||
"If non-nil, a regexp that matches any multi-line string closer.
|
||||
It may also match context.
|
||||
|
||||
A search for this regexp starting at the end of the corresponding
|
||||
opener must find the first closer as the first match.
|
||||
|
||||
Such a closer must include a \" character. (match-string 1)
|
||||
matches the actual delimiter and and (match-string 2) matches the
|
||||
actual \". If a delimiter contains several \"s, it is
|
||||
recommended to regard the last of them as \"the\" \"."
|
||||
t nil
|
||||
pike "\\(?:\\=\\|[^\\\"]\\)\\(?:\\\\.\\)*\\(\\(\"\\)\\)"
|
||||
c++ "\\()[^ ()\\n\r\t]\\{0,16\\}\\(\"\\)\\)")
|
||||
;; csharp "\\(?:\\=\\|[^\"]\\)\\(?:\"\"\\)*\\(\\(\"\\)\\)\\(?:[^\"]\\|\\'\\)"
|
||||
(c-lang-defvar c-ml-string-any-closer-re
|
||||
(c-lang-const c-ml-string-any-closer-re))
|
||||
|
||||
(c-lang-defconst c-ml-string-max-closer-len
|
||||
"If non-nil, the maximum length of a multi-line string closer.
|
||||
This must include the length of any \"context trailer\" following
|
||||
the actual closer and any \"context leader\" preceding it. This
|
||||
variable is ignored when `c-ml-string-back-closer-re' is non-nil."
|
||||
t nil
|
||||
c++ 18)
|
||||
(c-lang-defvar c-ml-string-max-closer-len
|
||||
(c-lang-const c-ml-string-max-closer-len))
|
||||
|
||||
(c-lang-defconst c-ml-string-max-closer-len-no-leader
|
||||
"If non-nil, the maximum length of a ml string closer without its leader.
|
||||
By \"leader\" is meant the context bytes preceding the actual
|
||||
multi-line string closer, that part of
|
||||
`c-ml-string-any-closer-re''s match preceding (match-beginning 1)."
|
||||
t nil
|
||||
pike 1
|
||||
;; 2
|
||||
;; 3
|
||||
c++ 18)
|
||||
(c-lang-defvar c-ml-string-max-closer-len-no-leader
|
||||
(c-lang-const c-ml-string-max-closer-len-no-leader))
|
||||
|
||||
(c-lang-defconst c-ml-string-back-closer-re
|
||||
"A regexp to move back out of a putative ml closer point is in.
|
||||
|
||||
This variable need only be non-nil for languages with multi-line
|
||||
string closers that can contain an indefinite length \"leader\"
|
||||
preceding the actual closer. It was designed for formats where
|
||||
an unbounded number of \\s or \"s might precede the closer
|
||||
proper, for example in Pike Mode or csharp-mode.
|
||||
|
||||
If point is in a putative multi-line string closer, a backward
|
||||
regexp search with `c-ml-string-back-closer-re' will leave point
|
||||
in a \"safe place\", from where a forward regexp search with
|
||||
`c-ml-string-any-closer-re' can test whether the original
|
||||
position was inside an actual closer.
|
||||
|
||||
When non-nil, this variable should end in \"\\\\\\==\". Note that
|
||||
such a backward search will match a minimal string, so a
|
||||
\"context character\" is probably needed at the start of the
|
||||
regexp. The value for csharp-mode would be something like
|
||||
\"\\\\(:?\\\\`\\\\|[^\\\"]\\\\)\\\"*\\\\\\==\"."
|
||||
t nil
|
||||
pike "\\(:?\\`\\|[^\\\"]\\)\\(:?\\\\.\\)*\\="
|
||||
;;pike ;; 2
|
||||
;; "\\(:?\\`\\|[^\"]\\)\"*\\="
|
||||
)
|
||||
(c-lang-defvar c-ml-string-back-closer-re
|
||||
(c-lang-const c-ml-string-back-closer-re))
|
||||
|
||||
(c-lang-defconst c-make-ml-string-closer-re-function
|
||||
"If non-nil, a function which creates a closer regexp matching an opener.
|
||||
|
||||
Such a function is given one argument, a multi-line opener (a
|
||||
string), and returns a regexp which will match the corresponding
|
||||
closer. When this regexp matches, (match-string 1) should be the
|
||||
actual closing delimiter, and (match-string 2) the \"active\" \"
|
||||
it contains.
|
||||
|
||||
A forward regexp search for this regexp starting at the end of
|
||||
the opener must find the closer as its first match."
|
||||
t (if (c-lang-const c-ml-string-any-closer-re)
|
||||
'c-ml-string-make-closer-re)
|
||||
c++ 'c-c++-make-ml-string-closer-re)
|
||||
(c-lang-defvar c-make-ml-string-closer-re-function
|
||||
(c-lang-const c-make-ml-string-closer-re-function))
|
||||
|
||||
(c-lang-defconst c-make-ml-string-opener-re-function
|
||||
"If non-nil, a function which creates an opener regexp matching a closer.
|
||||
|
||||
Such a function is given one argument, a multi-line closer (a
|
||||
string), and returns a regexp which will match the corresponding
|
||||
opener. When this regexp matches, (match-string 1) should be the
|
||||
actual opening delimiter, and (match-string 2) the \"active\" \"
|
||||
it contains.
|
||||
|
||||
A backward regexp search for this regexp starting at the start of
|
||||
the closer might not find the opener as its first match, should
|
||||
there be copies of the opener contained in the multi-line string."
|
||||
t (if (c-lang-const c-ml-string-opener-re)
|
||||
'c-ml-string-make-opener-re)
|
||||
c++ 'c-c++-make-ml-string-opener-re)
|
||||
(c-lang-defvar c-make-ml-string-opener-re-function
|
||||
(c-lang-const c-make-ml-string-opener-re-function))
|
||||
|
||||
(c-lang-defconst c-ml-string-cpp-or-opener-re
|
||||
;; A regexp which matches either a macro or a multi-line string opener.
|
||||
t (concat "\\("
|
||||
(or (c-lang-const c-anchored-cpp-prefix) "\\`a\\`")
|
||||
"\\)\\|\\("
|
||||
(or (c-lang-const c-ml-string-opener-re) "\\`a\\`")
|
||||
"\\)"))
|
||||
(c-lang-defvar c-ml-string-cpp-or-opener-re
|
||||
(c-lang-const c-ml-string-cpp-or-opener-re))
|
||||
|
||||
(c-lang-defconst c-cpp-or-ml-match-offset
|
||||
;; The offset to be added onto match numbers for a multi-line string in
|
||||
;; matches for `c-cpp-or-ml-string-opener-re'.
|
||||
t (if (c-lang-const c-anchored-cpp-prefix)
|
||||
(+ 2 (regexp-opt-depth (c-lang-const c-anchored-cpp-prefix)))
|
||||
2))
|
||||
(c-lang-defvar c-cpp-or-ml-match-offset
|
||||
(c-lang-const c-cpp-or-ml-match-offset))
|
||||
;; End of ml string section.
|
||||
|
||||
|
||||
(c-lang-defconst c-has-quoted-numbers
|
||||
"Whether the language has numbers quoted like 4'294'967'295."
|
||||
t nil
|
||||
|
|
@ -860,9 +1037,15 @@ literals."
|
|||
"Set if the language supports multiline string literals without escaped
|
||||
newlines. If t, all string literals are multiline. If a character,
|
||||
only literals where the open quote is immediately preceded by that
|
||||
literal are multiline."
|
||||
t nil
|
||||
pike ?#)
|
||||
literal are multiline.
|
||||
|
||||
Note that from CC Mode 5.36, this character use is obsolete,
|
||||
having been superseded by the \"multi-line string\" mechanism.
|
||||
If both mechanisms are set for a language, the newer one prevails
|
||||
over the old `c-multiline-string-start-char'. See the variables
|
||||
in the page containing `c-ml-string-opener-re' in cc-langs.el for
|
||||
further directions."
|
||||
t nil)
|
||||
(c-lang-defvar c-multiline-string-start-char
|
||||
(c-lang-const c-multiline-string-start-char))
|
||||
|
||||
|
|
|
|||
|
|
@ -1003,8 +1003,8 @@ Note that the style variables are always made local to the buffer."
|
|||
(goto-char (match-beginning 1))
|
||||
(setq m-beg (point))
|
||||
(c-end-of-macro)
|
||||
(when (c-major-mode-is 'c++-mode)
|
||||
(save-excursion (c-depropertize-raw-strings-in-region m-beg (point))))
|
||||
(when c-ml-string-opener-re
|
||||
(save-excursion (c-depropertize-ml-strings-in-region m-beg (point))))
|
||||
(c-clear-char-property-with-value m-beg (point) 'syntax-table '(1)))
|
||||
|
||||
(while (and (< (point) end)
|
||||
|
|
@ -1014,8 +1014,8 @@ Note that the style variables are always made local to the buffer."
|
|||
(setq m-beg (point))
|
||||
(c-end-of-macro))
|
||||
(when (and ss-found (> (point) end))
|
||||
(when (c-major-mode-is 'c++-mode)
|
||||
(save-excursion (c-depropertize-raw-strings-in-region m-beg (point))))
|
||||
(when c-ml-string-opener-re
|
||||
(save-excursion (c-depropertize-ml-strings-in-region m-beg (point))))
|
||||
(c-clear-char-property-with-value m-beg (point) 'syntax-table '(1)))
|
||||
|
||||
(while (and (< (point) c-new-END)
|
||||
|
|
@ -1023,8 +1023,8 @@ Note that the style variables are always made local to the buffer."
|
|||
(goto-char (match-beginning 1))
|
||||
(setq m-beg (point))
|
||||
(c-end-of-macro)
|
||||
(when (c-major-mode-is 'c++-mode)
|
||||
(save-excursion (c-depropertize-raw-strings-in-region m-beg (point))))
|
||||
(when c-ml-string-opener-re
|
||||
(save-excursion (c-depropertize-ml-strings-in-region m-beg (point))))
|
||||
(c-clear-char-property-with-value
|
||||
m-beg (point) 'syntax-table '(1)))))
|
||||
|
||||
|
|
@ -1174,12 +1174,15 @@ Note that the style variables are always made local to the buffer."
|
|||
)))))
|
||||
|
||||
(defun c-unescaped-nls-in-string-p (&optional quote-pos)
|
||||
;; Return whether unescaped newlines can be inside strings.
|
||||
;; Return whether unescaped newlines can be inside strings. If the current
|
||||
;; language handles multi-line strings, the value of this function is always
|
||||
;; nil.
|
||||
;;
|
||||
;; QUOTE-POS, if present, is the position of the opening quote of a string.
|
||||
;; Depending on the language, there might be a special character before it
|
||||
;; signifying the validity of such NLs.
|
||||
(cond
|
||||
(c-ml-string-opener-re nil)
|
||||
((null c-multiline-string-start-char) nil)
|
||||
((c-characterp c-multiline-string-start-char)
|
||||
(and quote-pos
|
||||
|
|
@ -1323,13 +1326,13 @@ Note that the style variables are always made local to the buffer."
|
|||
(setq pos (c-min-property-position pos c-max-syn-tab-mkr
|
||||
'c-fl-syn-tab))
|
||||
(when (< pos c-max-syn-tab-mkr)
|
||||
(goto-char pos))
|
||||
(when (and (save-match-data
|
||||
(c-search-backward-char-property-with-value-on-char
|
||||
'c-fl-syn-tab '(15) ?\"
|
||||
(max (- (point) 500) (point-min))))
|
||||
(not (equal (c-get-char-property (point) 'syntax-table) '(1))))
|
||||
(setq pos (1+ pos)))
|
||||
(goto-char pos)
|
||||
(when (and (save-match-data
|
||||
(c-search-backward-char-property-with-value-on-char
|
||||
'c-fl-syn-tab '(15) ?\"
|
||||
(max (- (point) 500) (point-min))))
|
||||
(not (equal (c-get-char-property (point) 'syntax-table) '(1))))
|
||||
(setq pos (1+ pos))))
|
||||
(while (< pos c-max-syn-tab-mkr)
|
||||
(setq pos
|
||||
(c-min-property-position pos c-max-syn-tab-mkr 'c-fl-syn-tab))
|
||||
|
|
@ -1435,7 +1438,8 @@ Note that the style variables are always made local to the buffer."
|
|||
;; quotes up until the next unescaped EOL. Also guard against the change
|
||||
;; being the insertion of \ before an EOL, escaping it.
|
||||
(cond
|
||||
((c-characterp c-multiline-string-start-char)
|
||||
((and (not c-ml-string-opener-re)
|
||||
(c-characterp c-multiline-string-start-char))
|
||||
;; The text about to be inserted might contain a multiline string
|
||||
;; opener. Set c-new-END after anything which might be affected.
|
||||
;; Go to the end of the putative multiline string.
|
||||
|
|
@ -1461,7 +1465,8 @@ Note that the style variables are always made local to the buffer."
|
|||
(< (point) (point-max))))))
|
||||
(setq c-new-END (max (point) c-new-END)))
|
||||
|
||||
(c-multiline-string-start-char
|
||||
((and (not c-ml-string-opener-re)
|
||||
c-multiline-string-start-char)
|
||||
(setq c-bc-changed-stringiness
|
||||
(not (eq (eq end-literal-type 'string)
|
||||
(eq beg-literal-type 'string))))
|
||||
|
|
@ -1506,7 +1511,7 @@ Note that the style variables are always made local to the buffer."
|
|||
;; Opening " at EOB.
|
||||
(c-clear-syn-tab (1- (point))))
|
||||
(when (and (c-search-backward-char-property 'syntax-table '(15) c-new-BEG)
|
||||
(memq (char-after) c-string-delims)) ; Ignore an unterminated raw string's (.
|
||||
(memq (char-after) c-string-delims)) ; Ignore an unterminated ml string's (.
|
||||
;; Opening " on last line of text (without EOL).
|
||||
(c-remove-string-fences)
|
||||
(setq c-new-BEG (min c-new-BEG (point))))))
|
||||
|
|
@ -1520,13 +1525,15 @@ Note that the style variables are always made local to the buffer."
|
|||
|
||||
(unless
|
||||
(or (and
|
||||
;; Don't set c-new-BEG/END if we're in a raw string.
|
||||
;; Don't set c-new-BEG/END if we're in an ml string.
|
||||
(eq beg-literal-type 'string)
|
||||
(c-at-c++-raw-string-opener (car beg-limits)))
|
||||
(c-ml-string-opener-at-or-around-point (car beg-limits)))
|
||||
(and c-multiline-string-start-char
|
||||
(not c-ml-string-opener-re)
|
||||
(not (c-characterp c-multiline-string-start-char))))
|
||||
(when (and (eq end-literal-type 'string)
|
||||
(not (eq (char-before (cdr end-limits)) ?\())
|
||||
(or (memq (char-before (cdr end-limits)) c-string-delims)
|
||||
(memq (char-before (cdr end-limits)) '(?\n ?\r)))
|
||||
(memq (char-after (car end-limits)) c-string-delims))
|
||||
(setq c-new-END (max c-new-END (cdr end-limits)))
|
||||
(when (equal (c-get-char-property (car end-limits) 'syntax-table)
|
||||
|
|
@ -1549,6 +1556,7 @@ Note that the style variables are always made local to the buffer."
|
|||
;; This function is called exclusively as an after-change function via
|
||||
;; `c-before-font-lock-functions'.
|
||||
(if (and c-multiline-string-start-char
|
||||
(not c-ml-string-opener-re)
|
||||
(not (c-characterp c-multiline-string-start-char)))
|
||||
;; Only the last " might need to be marked.
|
||||
(c-save-buffer-state
|
||||
|
|
@ -1591,6 +1599,7 @@ Note that the style variables are always made local to the buffer."
|
|||
((and (null beg-literal-type)
|
||||
(goto-char beg)
|
||||
(and (not (bobp))
|
||||
(not c-ml-string-opener-re)
|
||||
(eq (char-before) c-multiline-string-start-char))
|
||||
(memq (char-after) c-string-delims))
|
||||
(cons (point)
|
||||
|
|
@ -1615,6 +1624,7 @@ Note that the style variables are always made local to the buffer."
|
|||
(point))
|
||||
c-new-END))
|
||||
s)
|
||||
|
||||
(goto-char
|
||||
(cond ((null beg-literal-type)
|
||||
c-new-BEG)
|
||||
|
|
@ -1638,8 +1648,9 @@ Note that the style variables are always made local to the buffer."
|
|||
(and (memq (char-before) c-string-delims)
|
||||
(not (nth 4 s))))) ; Check we're actually out of the
|
||||
; comment. not stuck at EOB
|
||||
(unless (and (c-major-mode-is 'c++-mode)
|
||||
(c-maybe-re-mark-raw-string))
|
||||
(unless
|
||||
(and c-ml-string-opener-re
|
||||
(c-maybe-re-mark-ml-string))
|
||||
(if (c-unescaped-nls-in-string-p (1- (point)))
|
||||
(looking-at "\\(\\\\\\(.\\|\n\\)\\|[^\"]\\)*")
|
||||
(looking-at (cdr (assq (char-before) c-string-innards-re-alist))))
|
||||
|
|
@ -1678,21 +1689,15 @@ Note that the style variables are always made local to the buffer."
|
|||
(progn (goto-char end)
|
||||
(setq lit-start (c-literal-start)))
|
||||
(memq (char-after lit-start) c-string-delims)
|
||||
(or (not (c-major-mode-is 'c++-mode))
|
||||
(or (not c-ml-string-opener-re)
|
||||
(progn
|
||||
(goto-char lit-start)
|
||||
(and (not (and (eq (char-before) ?R)
|
||||
(looking-at c-c++-raw-string-opener-1-re)))
|
||||
(not (and (eq (char-after) ?\()
|
||||
(equal (c-get-char-property
|
||||
(point) 'syntax-table)
|
||||
'(15))))))
|
||||
(not (c-ml-string-opener-at-or-around-point)))
|
||||
(save-excursion
|
||||
(c-beginning-of-macro))))
|
||||
(goto-char (1+ end)) ; After the \
|
||||
;; Search forward for EOLL
|
||||
(setq lim (re-search-forward "\\(?:\\\\\\(?:.\\|\n\\)\\|[^\\\n\r]\\)*"
|
||||
nil t))
|
||||
;; Search forward for EOLL.
|
||||
(setq lim (c-point 'eoll))
|
||||
(goto-char (1+ end))
|
||||
(when (c-search-forward-char-property-with-value-on-char
|
||||
'syntax-table '(15) ?\" lim)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue