On Wed, Jul 3, 2019 at 7:25 PM Kévin Le Gouguec <address@hidden
> Looking at this situation from afar, invalid-syntax highlighting
> sounds exactly like the kind of feature that could be implemented as a
> flymake backend.
If you're not connecting these particular dots, I wrote Flymake (or
rather, I rewrote it) recently, so that's why I'm partial to it. But
there is also another very good and popular solution, Flycheck, which
does basically the same thing (but is not bundled with Emacs).
Anyway, if you open an Emacs C source and type M-x flymake-mode you
should already get the full syntax validation of the buffer as performed
by the compiler. In other projects, it's easy to setup (see the
docstring for the flymake-cc-command variable).
> - lifting some fontification code off CC mode since I assume the
> flymake frontend would handle the presentation,
> apart and banging on it until it fits flymake's API is not the path of
> least resistance.
It's not trivial to write a Flymake backend, but it's not hard either.
I wrote documentation for that in the manual and in docstrings. For this
, you don't need to lift any code off CC-mode (or any other mode) if it
follows basic assumptions. I hacked up a (very lightly tested) backend
that will diagnose unterminated multi-line strings in most modes.
This includes cc-derived modes if you monkey-patch them with
(defun c-unescaped-nls-in-string-p (&optional quote-pos) t)
...or if you find some other way to disable the problematic feature.
Here is the code.
(report-fn &key changes-start changes-end &allow-other-keys)
"Flymake backend for checking unterminated strings in c-like modes"
(cl-loop with collected = (list)
with start = (or changes-start (point-min))
with start-ppss = (syntax-ppss)
with end = (or changes-end (point-max))
initially (goto-char start)
(when (nth 3 start-ppss)
(goto-char (setq start (nth 8 start-ppss)))
(setq start-ppss (syntax-ppss)))
for ppss = start-ppss then (syntax-ppss)
for next = (if (and (nth 3 ppss)
(nth 8 ppss))
(let* ((lep (line-end-position))
(probe (char-before lep))
(1+ (scan-sexps (nth 8 ppss) 1)))))
(setq end (or string-end (point-max)))
((eq probe ?\\) (1+ lep))
((and (not (= lep (point))) (eq probe ?\"))
(t (push (flymake-make-diagnostic
(1+ lep) :error "unterminated string")
(and string-end (1+ string-end)))))
while (and next
(<= next end))
do (goto-char next)
finally (funcall report-fn
:region (cons start end))
You can try it with
(add-hook 'flymake-diagnostic-functions #'flymake-check-unterminated-strings nil t)
You might have to turn flymake off and on again. You also need a very
recent Flymake (version 1.0.8 should be in GNU ELPA shortly).