I'm trying to write a major mode for a programming language with JSX based syntax. Here's a minimal implementation.
(defun example-forward-parse-jsx (start-pos limit) "Move point past the JSX expression beginning at START-POS." (goto-char start-pos) (search-forward "</p>" limit t)) (defun example-font-lock-jsx (limit) "Search up to LIMIT for a JSX expression. If we find one, move point to its end, and set match data." (let ((start-pos nil) (end-pos nil)) (save-excursion (while (and (not end-pos) (re-search-forward (rx space (group "<")) limit t)) (setq start-pos (match-beginning 1)) (example-forward-parse-jsx start-pos limit) (setq end-pos (point)))) (when end-pos (set-match-data (list start-pos end-pos)) (goto-char end-pos)))) (defvar example-font-lock-keywords ;; Move over JSX expressions first, so we don't highlight their contents. '((example-font-lock-jsx (0 'default)) ("\\(let\\)" . font-lock-keyword-face))) (define-derived-mode example-mode prog-mode "Example" (setq-local font-lock-defaults '(example-font-lock-keywords)))
I want to treat
let as a keyword, except in JSX blocks. The following code:
let x = <p>foo let</p>;
Highlights correctly with the above major mode:
However, as soon as I insert a
'face text property (but not any other property), I end up with incorrect keyword highlighting inside my JSX expression.
(defun example-forward-parse-jsx (start-pos limit) "Move point past the JSX expression beginning at START-POS." (goto-char start-pos) (search-forward "</p>" limit t) (put-text-property (+ start-pos 1) (+ start-pos 2) 'face 'font-lock-type-face))
Whereas I want:
How can I set inner face properties inside a font-lock-keywords function?