[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] master 4d2b5bb 07/28: Font-lock JSX while editing it by ex
From: |
Jackson Ray Hamilton |
Subject: |
[Emacs-diffs] master 4d2b5bb 07/28: Font-lock JSX while editing it by extending regions |
Date: |
Tue, 9 Apr 2019 02:00:12 -0400 (EDT) |
branch: master
commit 4d2b5bbfebc040ca477f1156b44989b4e19bbc3e
Author: Jackson Ray Hamilton <address@hidden>
Commit: Jackson Ray Hamilton <address@hidden>
Font-lock JSX while editing it by extending regions
* lisp/progmodes/js.el (js-jsx--font-lock-keywords):
Call tag beginning and end matchers.
(js-jsx--match-tag-beg, js-jsx--match-tag-end): New functions.
(js-jsx--syntax-propertize-tag): Record buffer positions of JSXElement
beginning and end for font-locking.
(js--syntax-propertize-extend-region)
(js-jsx--syntax-propertize-extend-region): New functions for extending
the syntax-propertize region backwards to the start of a JSXElement so
its JSXAttribute children on its n+1th lines can be parsed as such
while editing those lines.
(js-mode): Add js--syntax-propertize-extend-region to
syntax-propertize-extend-region-functions.
---
lisp/progmodes/js.el | 81 +++++++++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 74 insertions(+), 7 deletions(-)
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 1319fa1..7fb4bcc 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -1496,8 +1496,10 @@ point of view of font-lock. It applies highlighting
directly with
(defconst js-jsx--font-lock-keywords
`((js-jsx--match-tag-name 0 font-lock-function-name-face t)
- (js-jsx--match-attribute-name 0 font-lock-variable-name-face t))
- "JSX font lock faces.")
+ (js-jsx--match-attribute-name 0 font-lock-variable-name-face t)
+ (js-jsx--match-tag-beg)
+ (js-jsx--match-tag-end))
+ "JSX font lock faces and multiline text properties.")
(defun js-jsx--match-tag-name (limit)
"Match JSXBoundaryElement names, until LIMIT."
@@ -1521,6 +1523,28 @@ point of view of font-lock. It applies highlighting
directly with
(progn (set-match-data value) t))
(js-jsx--match-attribute-name limit))))))
+(defun js-jsx--match-tag-beg (limit)
+ "Match JSXBoundaryElements from start, until LIMIT."
+ (when js-jsx-syntax
+ (let ((pos (next-single-char-property-change (point) 'js-jsx-tag-beg nil
limit))
+ value)
+ (when (and pos (> pos (point)))
+ (goto-char pos)
+ (or (and (setq value (get-text-property pos 'js-jsx-tag-beg))
+ (progn (put-text-property pos (cdr value)
'font-lock-multiline t) t))
+ (js-jsx--match-tag-beg limit))))))
+
+(defun js-jsx--match-tag-end (limit)
+ "Match JSXBoundaryElements from end, until LIMIT."
+ (when js-jsx-syntax
+ (let ((pos (next-single-char-property-change (point) 'js-jsx-tag-end nil
limit))
+ value)
+ (when (and pos (> pos (point)))
+ (goto-char pos)
+ (or (and (setq value (get-text-property pos 'js-jsx-tag-end))
+ (progn (put-text-property value pos 'font-lock-multiline t)
t))
+ (js-jsx--match-tag-end limit))))))
+
(defconst js--font-lock-keywords-3
`(
;; This goes before keywords-2 so it gets used preferentially
@@ -1769,11 +1793,53 @@ This performs fontification according to
`js--class-styles'."
"Check if STRING is a unary operator keyword in JavaScript."
(string-match-p js--unary-keyword-re string))
+(defun js--syntax-propertize-extend-region (start end)
+ "Extend the START-END region for propertization, if necessary.
+For use by `syntax-propertize-extend-region-functions'."
+ (if js-jsx-syntax (js-jsx--syntax-propertize-extend-region start end)))
+
+(defun js-jsx--syntax-propertize-extend-region (start end)
+ "Extend the START-END region for propertization, if necessary.
+If any “>” in the region appears to be the end of a tag starting
+before the start of the region, extend region backwards to the
+start of that tag so parsing may proceed from that point.
+For use by `syntax-propertize-extend-region-functions'."
+ (let (new-start
+ forward-sexp-function ; Use the Lisp version.
+ parse-sexp-lookup-properties) ; Fix backward-sexp error here.
+ (catch 'stop
+ (goto-char start)
+ (while (re-search-forward ">" end t)
+ (catch 'continue
+ ;; Check if this is really a right shift bitwise operator
+ ;; (“>>” or “>>>”).
+ (unless (or (eq (char-before (1- (point))) ?>)
+ (eq (char-after) ?>))
+ (save-excursion
+ (backward-char)
+ (while (progn (if (= (point) (point-min)) (throw 'continue nil))
+ (/= (char-before) ?<))
+ (skip-chars-backward " \t\n")
+ (if (= (point) (point-min)) (throw 'continue nil))
+ (cond
+ ((memq (char-before) '(?\" ?\' ?\` ?\}))
+ (condition-case nil
+ (backward-sexp)
+ (scan-error (throw 'continue nil))))
+ ((memq (char-before) '(?\/ ?\=)) (backward-char))
+ ((looking-back js--dotted-name-re (line-beginning-position) t)
+ (goto-char (match-beginning 0)))
+ (t (throw 'continue nil))))
+ (when (< (point) start)
+ (setq new-start (1- (point)))
+ (throw 'stop nil)))))))
+ (if new-start (cons new-start end))))
+
(defun js-jsx--syntax-propertize-tag (end)
"Determine if a JSXBoundaryElement is before END and propertize it.
Disambiguate JSX from inequality operators and arrow functions by
testing for syntax only valid as JSX."
- (let ((tag-beg (1- (point))) tag-end (type 'open)
+ (let ((tag-beg (1- (point))) (type 'open)
name-beg name-match-data unambiguous
forward-sexp-function) ; Use Lisp version.
(catch 'stop
@@ -1783,8 +1849,7 @@ testing for syntax only valid as JSX."
(cond
((= (char-after) ?>)
(forward-char)
- (setq unambiguous t
- tag-end (point))
+ (setq unambiguous t)
(throw 'stop nil))
;; Handle a JSXSpreadChild (“<Foo {...bar}”) or a
;; JSXExpressionContainer as a JSXAttribute value
@@ -1852,8 +1917,8 @@ testing for syntax only valid as JSX."
;; Save JSXBoundaryElement’s name’s match data for font-locking.
(if name-beg (put-text-property name-beg (1+ name-beg) 'js-jsx-tag-name
name-match-data))
;; Mark beginning and end of tag for features like indentation.
- (put-text-property tag-beg (1+ tag-beg) 'js-jsx-tag-beg type)
- (if tag-end (put-text-property (1- tag-end) tag-end 'js-jsx-tag-end
tag-beg)))))
+ (put-text-property tag-beg (1+ tag-beg) 'js-jsx-tag-beg (cons type
(point)))
+ (put-text-property (point) (1+ (point)) 'js-jsx-tag-end tag-beg))))
(defconst js-jsx--text-properties
'(js-jsx-tag-beg nil js-jsx-tag-end nil js-jsx-tag-name nil
js-jsx-attribute-name nil)
@@ -3945,6 +4010,8 @@ If one hasn't been set, or if it's stale, prompt for a
new one."
'(font-lock-syntactic-face-function
. js-font-lock-syntactic-face-function)))
(setq-local syntax-propertize-function #'js-syntax-propertize)
+ (add-hook 'syntax-propertize-extend-region-functions
+ #'js--syntax-propertize-extend-region 'append 'local)
(setq-local prettify-symbols-alist js--prettify-symbols-alist)
(setq-local parse-sexp-ignore-comments t)
- [Emacs-diffs] master updated (e1872f8 -> cf416d9), Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 27e9bce 03/28: Add new (failing) unclosed JSX test and separate such tests, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 2bedd23 09/28: Update expectations for JSX indentation in JSXAttribute space, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 16669d7 16/28: Fix counting of nested self-closing JSXOpeningElements, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 52a3113 06/28: Add basic JSX font-locking, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 339be7c 11/28: Finish replacing SGML-based JSX detection with js-mode’s parsing, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 8dae742 08/28: Propertize and font-lock JSXText and JSXExpressionContainers, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 3eadf1e 24/28: Identify JSX strings (for js2-mode), Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 4b305bb 02/28: Refactor JSX indentation code to improve enclosing JSX discovery, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 58c77f1 01/28: Add failing tests for JSX indentation bugs, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 4d2b5bb 07/28: Font-lock JSX while editing it by extending regions,
Jackson Ray Hamilton <=
- [Emacs-diffs] master 462baab 19/28: Add tests for miscellaneous JSX parsing feats, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master be86ece 04/28: js-syntax-propertize: Disambiguate JS from JSX, fixing some indents, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master d9d1bb2 14/28: Rename tests to use the “.jsx” file extension, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 84b1cfb 15/28: Indent broken arrow function bodies as an N+1th arg, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 6f53576 05/28: Use js-jsx- prefix for functions and variables, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master bf37078 12/28: Automatically detect JSX in JavaScript files, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master cf416d9 28/28: Explain reasonings for JSX syntax support design decisions, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 9545519 26/28: Add open/close parenthesis syntax to “<” and “>” in JSX, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 7c3ffda 27/28: Move curly functions closer to where they’re used, Jackson Ray Hamilton, 2019/04/09
- [Emacs-diffs] master 1a1ef28 10/28: Indent JSX as parsed in a JS context, Jackson Ray Hamilton, 2019/04/09