2

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:

screenshot

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))

This produces:

screenshot

Whereas I want:

screenshot

How can I set inner face properties inside a font-lock-keywords function?

  • Try using the property 'font-lock-face as opposed to 'face. – nega Apr 17 at 19:05
  • @nega the same behaviour occurs with 'font-lock-face. Looking at font-lock.el it looks like the two properties are treated the same (e.g. they're canonicalised in font-lock-prepend-text-property). – Wilfred Hughes Apr 18 at 10:02
  • i think your bounds are off. add more sample code. adding a couple more lines i get this: imgur.com/T5MjuTv – nega Apr 22 at 21:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.