Skip to content

Commit 7083974

Browse files
committed
* lisp/textmodes/sgml-mode.el: Fix lone > in sgml text
(sgml--syntax-propertize-ppss):New variable and function. (sgml-syntax-propertize-rules): Use it. Don't ignore quotes not followed by a matching quote or a '>' or '<'. (sgml-syntax-propertize): Set up sgml--syntax-propertize-ppss. * test/lisp/textmodes/sgml-mode-tests.el (sgml-tests--quotes-syntax): Add test for lone '>'.
1 parent dfed333 commit 7083974

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

lisp/textmodes/sgml-mode.el

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,24 @@ Any terminating `>' or `/' is not matched.")
328328
(defvar sgml-font-lock-keywords sgml-font-lock-keywords-1
329329
"Rules for highlighting SGML code. See also `sgml-tag-face-alist'.")
330330

331+
(defvar-local sgml--syntax-propertize-ppss nil)
332+
333+
(defun sgml--syntax-propertize-ppss (pos)
334+
"Return PPSS at POS, fixing the syntax of any lone `>' along the way."
335+
(cl-assert (>= pos (car sgml--syntax-propertize-ppss)))
336+
(let ((ppss (parse-partial-sexp (car sgml--syntax-propertize-ppss) pos -1
337+
nil (cdr sgml--syntax-propertize-ppss))))
338+
(while (eq -1 (car ppss))
339+
(put-text-property (1- (point)) (point)
340+
'syntax-table (string-to-syntax "."))
341+
;; Hack attack: rather than recompute the ppss from
342+
;; (car sgml--syntax-propertize-ppss), we manually "fix it".
343+
(setcar ppss 0)
344+
(setq ppss (parse-partial-sexp (point) pos -1 nil ppss)))
345+
(setcdr sgml--syntax-propertize-ppss ppss)
346+
(setcar sgml--syntax-propertize-ppss pos)
347+
ppss))
348+
331349
(eval-and-compile
332350
(defconst sgml-syntax-propertize-rules
333351
(syntax-propertize-precompile-rules
@@ -344,23 +362,28 @@ Any terminating `>' or `/' is not matched.")
344362
;; the resulting number of calls to syntax-ppss made it too slow
345363
;; (bug#33887), so we're now careful to leave alone any pair
346364
;; of quotes that doesn't hold a < or > char, which is the vast majority.
347-
("\\(?:\\(?1:\"\\)[^\"<>]*[<>\"]\\|\\(?1:'\\)[^'<>]*[<>']\\)"
348-
(1 (unless (memq (char-before) '(?\' ?\"))
365+
("\\(?:\\(?1:\"\\)[^\"<>]*\\|\\(?1:'\\)[^'\"<>]*\\)"
366+
(1 (if (eq (char-after) (char-after (match-beginning 0)))
367+
(forward-char 1)
349368
;; Be careful to call `syntax-ppss' on a position before the one
350369
;; we're going to change, so as not to need to flush the data we
351370
;; just computed.
352-
(if (prog1 (zerop (car (syntax-ppss (match-beginning 0))))
353-
(goto-char (1- (match-end 0))))
371+
(if (zerop (save-excursion
372+
(car (sgml--syntax-propertize-ppss
373+
(match-beginning 0)))))
354374
(string-to-syntax ".")))))
355375
)))
356376

357377
(defun sgml-syntax-propertize (start end)
358378
"Syntactic keywords for `sgml-mode'."
359-
(goto-char start)
379+
(setq sgml--syntax-propertize-ppss (cons start (syntax-ppss start)))
380+
(cl-assert (>= (cadr sgml--syntax-propertize-ppss) 0))
360381
(sgml-syntax-propertize-inside end)
361382
(funcall
362383
(syntax-propertize-rules sgml-syntax-propertize-rules)
363-
start end))
384+
start end)
385+
;; Catch any '>' after the last quote.
386+
(sgml--syntax-propertize-ppss end))
364387

365388
(defun sgml-syntax-propertize-inside (end)
366389
(let ((ppss (syntax-ppss)))

test/lisp/textmodes/sgml-mode-tests.el

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,10 @@ The point is set to the beginning of the buffer."
165165
(sgml-mode)
166166
(insert "a\"b <tag>c'd</tag>")
167167
(should (= 1 (car (syntax-ppss (1- (point-max))))))
168+
(should (= 0 (car (syntax-ppss (point-max)))))
169+
(erase-buffer)
170+
(insert "<tag>c>d</tag>")
171+
(should (= 1 (car (syntax-ppss (1- (point-max))))))
168172
(should (= 0 (car (syntax-ppss (point-max)))))))
169173

170174
(provide 'sgml-mode-tests)

0 commit comments

Comments
 (0)