diff options
Diffstat (limited to 'configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645')
4 files changed, 0 insertions, 1422 deletions
diff --git a/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode-autoloads.el b/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode-autoloads.el deleted file mode 100644 index 1323470ce1f5..000000000000 --- a/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode-autoloads.el +++ /dev/null @@ -1,43 +0,0 @@ -;;; rjsx-mode-autoloads.el --- automatically extracted autoloads -;; -;;; Code: -(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) - -;;;### (autoloads nil "rjsx-mode" "rjsx-mode.el" (23450 31811 168601 -;;;;;; 424000)) -;;; Generated autoloads from rjsx-mode.el - -(autoload 'rjsx-mode "rjsx-mode" "\ -Major mode for editing JSX files. - -\(fn)" t nil) - -(autoload 'rjsx-minor-mode "rjsx-mode" "\ -Minor mode for parsing JSX syntax into an AST. - -\(fn &optional ARG)" t nil) - -(add-to-list 'auto-mode-alist '("\\.jsx\\'" . rjsx-mode)) - -(autoload 'rjsx-comment-dwim "rjsx-mode" "\ -RJSX implementation of `comment-dwim'. If called on a region, -this function delegates to `comment-or-uncomment-region'. If the -point is not in a JSX context, it delegates to the -`comment-dwim', otherwise it will comment the JSX AST node at -point using the apppriate comment delimiters. - -For example: If point is on a JSX attribute or JSX expression, it -will comment the entire attribute using \"/* */\". , otherwise if -it's on a descendent JSX Element, it will use \"{/* */}\" -instead. - -\(fn ARG)" t nil) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: -;;; rjsx-mode-autoloads.el ends here diff --git a/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode-pkg.el b/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode-pkg.el deleted file mode 100644 index 237f0b804083..000000000000 --- a/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; -*- no-byte-compile: t -*- -(define-package "rjsx-mode" "20180823.1645" "Real support for JSX" '((emacs "24.4") (js2-mode "20170504")) :commit "c463a162a2557668f624c32dd5c3b58512e80b1a" :keywords '("languages") :authors '(("Felipe Ochoa" . "felipe@fov.space")) :maintainer '("Felipe Ochoa" . "felipe@fov.space") :url "https://github.com/felipeochoa/rjsx-mode/") diff --git a/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode.el b/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode.el deleted file mode 100644 index 9f43b1699586..000000000000 --- a/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode.el +++ /dev/null @@ -1,1377 +0,0 @@ -;;; rjsx-mode.el --- Real support for JSX -*- lexical-binding: t -*- - -;; Copyright (C) 2016 Felipe Ochoa - -;; Author: Felipe Ochoa <felipe@fov.space> -;; URL: https://github.com/felipeochoa/rjsx-mode/ -;; Package-Version: 20180823.1645 -;; Package-Requires: ((emacs "24.4") (js2-mode "20170504")) -;; Version: 1.1 -;; Keywords: languages - -;;; Commentary: -;; Defines a major mode `rjsx-mode' based on `js2-mode' for editing -;; JSX files. `rjsx-mode' extends the parser in `js2-mode' to support -;; the full JSX syntax. This means you get all of the `js2' features -;; plus proper syntax checking and highlighting of JSX code blocks. -;; -;; Some features that this mode adds to js2: -;; -;; - Highlighting JSX tag names and attributes (using the rjsx-tag and -;; rjsx-attr faces) -;; - Highlight undeclared JSX components -;; - Parsing the spread operator {...otherProps} -;; - Parsing && and || in child expressions {cond && <BigComponent/>} -;; - Parsing ternary expressions {toggle ? <ToggleOn /> : <ToggleOff />} -;; -;; Additionally, since rjsx-mode extends the js2 AST, utilities using -;; the parse tree gain access to the JSX structure. - -;;; Code: - -;;;; Basic mode definitions - -(require 'cl-lib) -(require 'js2-mode) -(eval-when-compile (require 'subr-x)) -(require 'newcomment) - -(defgroup rjsx-mode nil - "Support for JSX." - :group 'js2-mode) - -(defcustom rjsx-max-size-for-frequent-reparse 100000 - "Buffers with fewer than this many characters will be parsed more frequently. -Set this to 0 to disable the reparsing altogether. The frequent -parsing supports the magic `rjsx-electric-lt' and -`rjsx-delete-creates-full-tag' behaviors." - :group 'rjsx-mode - :type 'integer) - -;;;###autoload -(define-derived-mode rjsx-mode js2-jsx-mode "RJSX" - "Major mode for editing JSX files." - :lighter ":RJSX" - :group 'rjsx-mode - (setq-local comment-use-syntax nil) - (setq-local comment-start-skip "[[:space:]]*\\(//+\\|{?/\\*+\\)") - ;; \n is included to get arround `comment-normalize-vars' and `comment-only-p' - (setq-local comment-end-skip "\\(\\*+/}?[[:space:]]*\\)\n?\\|\n") - (setq-local comment-region-function 'rjsx-comment-region-function) - (setq-local uncomment-region-function 'rjsx-uncomment-region-function) - (setq-local comment-quote-nested-function 'rjsx-comment-quote-nested-function) - (setq-local indent-line-function 'rjsx-indent-line) - (setq-local indent-region-function 'rjsx-indent-region)) - -;;;###autoload -(define-minor-mode rjsx-minor-mode - "Minor mode for parsing JSX syntax into an AST." - :lighter " rjsx" - (if rjsx-minor-mode - (js2-minor-mode 1) - (js2-minor-mode 0))) - -;;;###autoload -(add-to-list 'auto-mode-alist '("\\.jsx\\'" . rjsx-mode)) - -(defun rjsx-parse-xml-initializer (orig-fun) - "Dispatch the xml parser based on variable `rjsx-mode' being active or not. -This function is used to advise `js2-parse-xml-initializer' (ORIG-FUN) using -the `:around' combinator. JS2-PARSER is the original XML parser." - (if (or (eq major-mode 'rjsx-mode) rjsx-minor-mode) - (rjsx-parse-top-xml) - (apply orig-fun nil))) - -(advice-add 'js2-parse-xml-initializer :around #'rjsx-parse-xml-initializer) - -(defun rjsx-unadvice-js2 () - "Remove the rjsx advice on the js2 parser. This will cause rjsx to stop working globally." - (advice-remove 'js2-parse-xml-initializer #'rjsx-parse-xml-initializer) - (advice-remove 'js--looking-at-operator-p #'rjsx--js--looking-at-operator-p-advice)) - - -(defface rjsx-tag - '((t . (:inherit font-lock-function-name-face))) - "`rjsx-mode' face used to highlight JSX tag names." - :group 'rjsx-mode) - -(defface rjsx-attr - '((t . (:inherit font-lock-variable-name-face))) - "`rjsx-mode' face used to highlight JSX attribute names." - :group 'rjsx-mode) - -(defface rjsx-text - '((t . (:inherit font-lock-string-face))) - "`rjsx-mode' face used to highlight JSX text." - :group 'rjsx-mode) - -(defface rjsx-tag-bracket-face - '((t . (:inherit default))) - "`rjsx-mode' face used to highlight `<', `/', and `>'." - :group 'rjsx-mode) - - -;;;; Parser constants struct definitions - -;; Token types for XML nodes. We need to re-use some unused values to -;; not mess up the vectors that js2 has set up -(defvar rjsx-JSX js2-ENUM_INIT_KEYS) -(defvar rjsx-JSX-CLOSE js2-ENUM_INIT_VALUES) -(defvar rjsx-JSX-IDENT js2-ENUM_INIT_ARRAY) -(defvar rjsx-JSX-MEMBER js2-ENUM_NEXT) -(defvar rjsx-JSX-ATTR js2-ENUM_ID) -(defvar rjsx-JSX-SPREAD js2-REF_NS_MEMBER) -(defvar rjsx-JSX-TEXT js2-ESCXMLTEXT) -(defvar rjsx-JSX-EXPRESSION js2-ESCXMLATTR) - -(dolist (sym '(rjsx-JSX rjsx-JSX-CLOSE rjsx-JSX-IDENT rjsx-JSX-MEMBER rjsx-JSX-ATTR - rjsx-JSX-SPREAD rjsx-JSX-TEXT rjsx-JSX-EXPRESSION)) - (aset js2-token-names (symbol-value sym) (downcase (substring (symbol-name sym) 5))) - (puthash sym (symbol-value sym) js2-token-codes)) - -(js2-msg "msg.bad.jsx.ident" "invalid JSX identifier") -(js2-msg "msg.invalid.jsx.string" "invalid JSX string (cannot contain delimiter in string body)") -(js2-msg "msg.mismatched.close.tag" "mismatched closing JSX tag; expected `%s'") -(js2-msg "msg.no.gt.in.opener" "missing `>' in opening tag") -(js2-msg "msg.no.gt.in.closer" "missing `>' in closing tag") -(js2-msg "msg.no.gt.after.slash" "missing `>' after `/' in self-closing tag") -(js2-msg "msg.no.rc.after.spread" "missing `}' after spread-prop") -(js2-msg "msg.no.value.after.jsx.prop" "missing value after prop `%s'") -(js2-msg "msg.no.dots.in.prop.spread" "missing `...' in spread prop") -(js2-msg "msg.no.rc.after.expr" "missing `}' after expression") -(js2-msg "msg.empty.expr" "empty `{}' expression") - - -(cl-defstruct (rjsx-node - (:include js2-node (type rjsx-JSX)) - (:constructor nil) - (:constructor make-rjsx-node - (&key (pos (js2-current-token-beg)) - len - name - rjsx-props - kids))) - name ; AST node containing the parsed xml name or nil for fragments - rjsx-props ; linked list of AST nodes (both attributes and spreads) - kids ; linked list of child xml nodes - closing-tag) ; AST node with the tag closer - - -(js2--struct-put 'rjsx-node 'js2-visitor 'rjsx-node-visit) -(js2--struct-put 'rjsx-node 'js2-printer 'rjsx-node-print) -(defun rjsx-node-visit (ast callback) - "Visit the `rjsx-node' children of AST, invoking CALLBACK on them." - (let ((name (rjsx-node-name ast))) - (when name (js2-visit-ast name callback))) - (dolist (prop (rjsx-node-rjsx-props ast)) - (js2-visit-ast prop callback)) - (dolist (prop (rjsx-node-kids ast)) - (js2-visit-ast prop callback)) - (when (rjsx-node-closing-tag ast) - (js2-visit-ast (rjsx-node-closing-tag ast) callback))) - -(defun rjsx-node-print (node indent-level) - "Print the `rjsx-node' NODE at indent level INDENT-LEVEL." - (insert (js2-make-pad indent-level) "<") - (let ((name-n (rjsx-node-name node))) - (when name-n (js2-print-ast name-n 0))) - (dolist (attr (rjsx-node-rjsx-props node)) - (insert " ") - (js2-print-ast attr 0)) - (let ((closer (rjsx-node-closing-tag node))) - (if (null closer) - (insert "/>") - (insert ">") - (dolist (child (rjsx-node-kids node)) - (js2-print-ast child 0)) - (js2-print-ast closer indent-level)))) - -(defun rjsx-node-opening-tag-name (node) - "Return a string with NODE's opening tag including any namespace and member operations." - (let ((name-n (rjsx-node-name node))) - (cond - ((null name-n) "") ; fragment - ((rjsx-member-p name-n) (rjsx-member-full-name name-n)) - ((rjsx-identifier-p name-n) (rjsx-identifier-full-name name-n)) - (t "")))) ; js2-error-node - -(defun rjsx-node-push-prop (n rjsx-prop) - "Extend rjsx-node N's rjsx-props with js2-node RJSX-PROP. -Sets JSX-PROPS's parent to N." - (let ((rjsx-props (rjsx-node-rjsx-props n))) - (if rjsx-props - (setcdr rjsx-props (nconc (cdr rjsx-props) (list rjsx-prop))) - (setf (rjsx-node-rjsx-props n) (list rjsx-prop)))) - (js2-node-add-children n rjsx-prop)) - -(defun rjsx-node-push-child (n kid) - "Extend rjsx-node N's children with js2-node KID. -Sets KID's parent to N." - (let ((kids (rjsx-node-kids n))) - (if kids - (setcdr kids (nconc (cdr kids) (list kid))) - (setf (rjsx-node-kids n) (list kid)))) - (js2-node-add-children n kid)) - - -(cl-defstruct (rjsx-closing-tag - (:include js2-node (type rjsx-JSX-CLOSE)) - (:constructor nil) - (:constructor make-rjsx-closing-tag (&key pos len name))) - name) ; An rjsx-identifier or rjsx-member node or nil for fragments - -(js2--struct-put 'rjsx-closing-tag 'js2-visitor 'rjsx-closing-tag-visit) -(js2--struct-put 'rjsx-closing-tag 'js2-printer 'rjsx-closing-tag-print) - -(defun rjsx-closing-tag-visit (ast callback) - "Visit the `rjsx-closing-tag' children of AST, invoking CALLBACK on them." - (js2-visit-ast (rjsx-closing-tag-name ast) callback)) - -(defun rjsx-closing-tag-print (node indent-level) - "Print the `rjsx-closing-tag' NODE at INDENT-LEVEL." - (insert (js2-make-pad indent-level) "</" (rjsx-closing-tag-full-name node) ">")) - -(defun rjsx-closing-tag-full-name (n) - "Return the string with N's fully-namespaced name, or just name if it's not namespaced." - (let ((child (rjsx-closing-tag-name n))) - (cond - ((null child) "") ; fragment - ((rjsx-member-p child) (rjsx-member-full-name child)) - ((rjsx-identifier-p child) (rjsx-identifier-full-name child)) - (t "")))) - -(cl-defstruct (rjsx-identifier - (:include js2-node (type rjsx-JSX-IDENT)) - (:constructor nil) - (:constructor make-rjsx-identifier (&key (pos (js2-current-token-beg)) - len namespace name))) - (namespace nil) - name) ; js2-name-node - -(js2--struct-put 'rjsx-identifier 'js2-visitor 'rjsx-identifier-visit) -(js2--struct-put 'rjsx-identifier 'js2-printer 'rjsx-identifier-print) - -(defun rjsx-identifier-visit (n callback) - "Visit N's children can call CALLBACK on them." - (js2-visit-ast (rjsx-identifier-name n) callback)) - -(defun rjsx-identifier-print (node indent-level) - "Print the `rjsx-identifier' NODE at INDENT-LEVEL." - (insert (js2-make-pad indent-level) (rjsx-identifier-full-name node))) - -(defun rjsx-identifier-full-name (n) - "Return the string with N's fully-namespaced name, or just name if it's not namespaced." - (if (rjsx-identifier-namespace n) - (format "%s:%s" (rjsx-identifier-namespace n) (js2-name-node-name (rjsx-identifier-name n))) - (js2-name-node-name (rjsx-identifier-name n)))) - -(cl-defstruct (rjsx-member - (:include js2-node (type rjsx-JSX-MEMBER)) - (:constructor nil) - (:constructor make-rjsx-member (&key pos len dots-pos idents))) - dots-pos ; List of positions of each dot - idents) ; List of rjsx-identifier nodes - -(js2--struct-put 'rjsx-member 'js2-visitor 'rjsx-member-visit) -(js2--struct-put 'rjsx-member 'js2-printer 'rjsx-member-print) - -(defun rjsx-member-visit (n callback) - "Visit N's children and call CALLBACK on them." - (dolist (ident (rjsx-member-idents n)) - (js2-visit-ast ident callback))) - -(defun rjsx-member-print (node indent-level) - "Print the `rjsx-member' NODE at INDENT-LEVEL." - (insert (js2-make-pad indent-level) (rjsx-member-full-name node))) - -(defun rjsx-member-full-name (n) - "Return the string with N's combined names together." - (mapconcat 'rjsx-identifier-full-name (rjsx-member-idents n) ".")) - -(cl-defstruct (rjsx-attr - (:include js2-node (type rjsx-JSX-ATTR)) - (:constructor nil) - (:constructor make-rjsx-attr (&key (pos (js2-current-token-beg)) - len name value))) - name ; a rjsx-identifier - value) ; a js2-expression - -(js2--struct-put 'rjsx-attr 'js2-visitor 'rjsx-attr-visit) -(js2--struct-put 'rjsx-attr 'js2-printer 'rjsx-attr-print) - -(defun rjsx-attr-visit (ast callback) - "Visit the `rjsx-attr' children of AST, invoking CALLBACK on them." - (js2-visit-ast (rjsx-attr-name ast) callback) - (js2-visit-ast (rjsx-attr-value ast) callback)) - -(defun rjsx-attr-print (node indent-level) - "Print the `rjsx-attr' NODE at INDENT-LEVEL." - (js2-print-ast (rjsx-attr-name node) indent-level) - (unless (js2-empty-expr-node-p (rjsx-attr-value node)) - (insert "=") - (js2-print-ast (rjsx-attr-value node) 0))) - -(cl-defstruct (rjsx-spread - (:include js2-node (type rjsx-JSX-SPREAD)) - (:constructor nil) - (:constructor make-rjsx-spread (&key pos len expr))) - expr) ; a js2-expression - -(js2--struct-put 'rjsx-spread 'js2-visitor 'rjsx-spread-visit) -(js2--struct-put 'rjsx-spread 'js2-printer 'rjsx-spread-print) - -(defun rjsx-spread-visit (ast callback) - "Visit the `rjsx-spread' children of AST, invoking CALLBACK on them." - (js2-visit-ast (rjsx-spread-expr ast) callback)) - -(defun rjsx-spread-print (node indent-level) - "Print the `rjsx-spread' NODE at INDENT-LEVEL." - (insert (js2-make-pad indent-level) "{...") - (js2-print-ast (rjsx-spread-expr node) 0) - (insert "}")) - -(cl-defstruct (rjsx-wrapped-expr - (:include js2-node (type rjsx-JSX-TEXT)) - (:constructor nil) - (:constructor make-rjsx-wrapped-expr (&key pos len child))) - child) - -(js2--struct-put 'rjsx-wrapped-expr 'js2-visitor 'rjsx-wrapped-expr-visit) -(js2--struct-put 'rjsx-wrapped-expr 'js2-printer 'rjsx-wrapped-expr-print) - -(defun rjsx-wrapped-expr-visit (ast callback) - "Visit the `rjsx-wrapped-expr' child of AST, invoking CALLBACK on them." - (js2-visit-ast (rjsx-wrapped-expr-child ast) callback)) - -(defun rjsx-wrapped-expr-print (node indent-level) - "Print the `rjsx-wrapped-expr' NODE at INDENT-LEVEL." - (insert (js2-make-pad indent-level) "{") - (js2-print-ast (rjsx-wrapped-expr-child node) indent-level) - (insert "}")) - -(cl-defstruct (rjsx-text - (:include js2-node (type rjsx-JSX-TEXT)) - (:constructor nil) - (:constructor make-rjsx-text (&key (pos (js2-current-token-beg)) - (len (js2-current-token-len)) - value))) - value) ; a string - -(js2--struct-put 'rjsx-text 'js2-visitor 'js2-visit-none) -(js2--struct-put 'rjsx-text 'js2-printer 'rjsx-text-print) - -(defun rjsx-text-print (node _indent-level) - "Print the `rjsx-text' NODE at INDENT-LEVEL." - ;; Text nodes include whitespace - (insert (rjsx-text-value node))) - - -;;;; Recursive descent parsing -(defvar rjsx-print-debug-message nil "If t will print out debug messages.") -;(setq rjsx-print-debug-message t) -(defmacro rjsx-maybe-message (&rest args) - "If debug is enabled, call `message' with ARGS." - `(when rjsx-print-debug-message - (message ,@args))) - - -(defvar rjsx-text-syntax-table - (let ((table (make-syntax-table (standard-syntax-table)))) - ;; `js-indent-line' assumes that \n is not whitespace - ;; Since it's not a comment delimiter in JSX text, punctuation - ;; is the only other (semi) logical choice - (modify-syntax-entry ?\n "." table) - table)) - -(js2-deflocal rjsx-in-xml nil "Variable used to track which xml parsing function is the outermost one.") - -(define-error 'rjsx-eof-while-parsing "RJSX: EOF while parsing") - -(defmacro rjsx-handling-eof (&rest body) - "Execute BODY and return the result of the last form. -If BODY signals `rjsx-eof-while-parsing', instead report a syntax -error and return a `js2-error-node'." - `(let ((beg (js2-current-token-beg))) - (condition-case nil - (progn ,@body) - (rjsx-eof-while-parsing - (let ((len (- js2-ts-cursor beg))) - (rjsx-maybe-message (format "Handling eof from %d" beg)) - (js2-report-error "msg.syntax" nil beg len) - (make-js2-error-node :pos beg :len len)))))) - -(defsubst rjsx-record-tag-bracket-face () - "Fontify the current token with `rjsx-tag-bracket-face'." - (js2-set-face (js2-current-token-beg) (js2-current-token-end) 'rjsx-tag-bracket-face 'record)) - -(defsubst rjsx-record-token-class (cls) - "Record an 'rjsx-class text property with value CLS for the current token." - (js2-record-text-property (js2-current-token-beg) (js2-current-token-end) - 'rjsx-class cls)) - -(defun rjsx-parse-top-xml () - "Parse a top level XML fragment. -This is the entry point when ‘js2-parse-unary-expr’ finds a '<' character" - (if rjsx-in-xml - (rjsx-parse-xml) - (let ((rjsx-in-xml t)) - (rjsx-handling-eof (rjsx-parse-xml))))) - -(defun rjsx-parse-xml () - "Parse a complete xml node from start to end tag." - (rjsx-record-token-class '<) - (rjsx-record-tag-bracket-face) - (let ((pn (make-rjsx-node)) self-closing name-n name-str child child-name-str is-fragment) - (rjsx-maybe-message "Starting rjsx-parse-xml after <") - (if (setq child (rjsx-parse-empty-tag)) - child - (if (eq (js2-peek-token) js2-GT) - (setq is-fragment t) - (setf (rjsx-node-name pn) (setq name-n (rjsx-parse-member-or-ns 'rjsx-tag))) - (if (js2-error-node-p name-n) - (progn (rjsx-maybe-message "could not parse tag name") - (make-js2-error-node :pos (js2-node-pos pn) :len (1+ (js2-node-len name-n)))) - (js2-node-add-children pn name-n) - (if js2-highlight-external-variables - (let ((name-node (rjsx-identifier-name - (if (rjsx-member-p name-n) - (car (rjsx-member-idents name-n)) - name-n))) - (case-fold-search nil)) - (when (string-match-p "^[[:upper:]]" (js2-name-node-name name-node)) - (js2-record-name-node name-node))))) - (rjsx-maybe-message "cleared tag name: '%s'" name-str) - ;; Now parse the attributes - (rjsx-parse-attributes pn) - (rjsx-maybe-message "cleared attributes")) - (setq name-str (rjsx-node-opening-tag-name pn)) - (progn - ;; Now parse either a self closing tag or the end of the opening tag - (rjsx-maybe-message "next type: `%s'" (js2-peek-token)) - (if (setq self-closing (js2-match-token js2-DIV)) - (progn - (rjsx-record-token-class 'self-closing-slash) - (rjsx-record-tag-bracket-face) - ;; TODO: How do we un-mark old slashes? - (when (js2-must-match js2-GT "msg.no.gt.after.slash" - (js2-node-pos pn) (- (js2-current-token-end) (js2-node-pos pn))) - (rjsx-record-token-class '>) - (rjsx-record-tag-bracket-face))) - (when (js2-must-match js2-GT "msg.no.gt.in.opener" (js2-node-pos pn) (js2-node-len pn)) - (rjsx-record-token-class '>) - (rjsx-record-tag-bracket-face))) - (rjsx-maybe-message "cleared opener closer, self-closing: %s" self-closing) - (if self-closing - (setf (js2-node-len pn) (- (js2-current-token-end) (js2-node-pos pn))) - (while (not (rjsx-closing-tag-p (setq child (rjsx-parse-child is-fragment)))) - ;; rjsx-parse-child calls our scanner, which always moves - ;; forward at least one character. If it hits EOF, it - ;; signals to our caller, so we don't have to worry about infinite loops here - (rjsx-maybe-message "parsed child") - (rjsx-node-push-child pn child) - (if (= 0 (js2-node-len child)) ; TODO: Does this ever happen? - (js2-get-token))) - (setq child-name-str (rjsx-closing-tag-full-name child)) - (unless (string= name-str child-name-str) - (js2-report-error "msg.mismatched.close.tag" name-str (js2-node-pos child) (js2-node-len child))) - (rjsx-maybe-message "cleared children for `%s'" name-str) - (js2-node-add-children pn child) - (setf (rjsx-node-closing-tag pn) child)) - (rjsx-maybe-message "Returning completed XML node") - (setf (js2-node-len pn) (- (js2-current-token-end) (js2-node-pos pn))) - pn)))) - -(defun rjsx-parse-empty-tag () - "Check if we are in an empty tag of the form `</>' and consume it if so. -Returns a `js2-error-node' if we are in one or nil if not." - (let ((beg (js2-current-token-beg))) - (when (js2-match-token js2-DIV) - (if (js2-match-token js2-GT) - (progn ; We're in a </> block, likely created by us in `rjsx-electric-lt' - ;; We only highlight the < to reduce the visual impact - (js2-report-error "msg.syntax" nil beg 1) - (make-js2-error-node :pos beg :len (- (js2-current-token-end) beg))) - ;; TODO: This is probably an unmatched closing tag. We should - ;; consume it, mark it an error, and move on - (js2-unget-token) - nil)))) - -(defun rjsx-parse-attributes (parent) - "Parse all attributes, including key=value and {...spread}, and add them to PARENT." - ;; Getting this function to not hang in the loop proved tricky. The - ;; key is that `rjsx-parse-spread' and `rjsx-parse-single-attr' both - ;; return `js2-error-node's if they fail to consume any tokens, - ;; which signals to us that we just need to discard one token and - ;; keep going. - (let (attr - (loop-terminators (list js2-DIV js2-GT js2-EOF js2-ERROR))) - (while (not (memql (js2-peek-token) loop-terminators)) - (rjsx-maybe-message "Starting loop. Next token type: %s\nToken pos: %s" (js2-peek-token) (js2-current-token-beg)) - (setq attr - (if (js2-match-token js2-LC) - (or (rjsx-check-for-empty-curlies t) - (prog1 (rjsx-parse-spread) - (rjsx-maybe-message "Parsed spread"))) - (rjsx-maybe-message "Parsing single attr") - (rjsx-parse-single-attr))) - (when (js2-error-node-p attr) (js2-get-token)) - ; TODO: We should make this conditional on - ; `js2-recover-from-parse-errors' - (rjsx-node-push-prop parent attr)))) - - -(cl-defun rjsx-check-for-empty-curlies (&optional dont-consume-rc &key check-for-comments warning) - "If the following token is '}' set empty curly errors. -If DONT-CONSUME-RC is non-nil, the matched right curly token -won't be consumed. Returns a `js2-error-node' if the curlies are -empty or nil otherwise. If CHECK-FOR-COMMENTS (a &KEY argument) -is non-nil, this will check for comments inside the curlies and -returns a `js2-empty-expr-node' if any are found. If WARNING (a -&key argument) is non-nil, reports the empty curlies as a warning -and not an error and also returns a `js2-empty-expr-node'. -Assumes the current token is a '{'." - (let ((beg (js2-current-token-beg)) end len) - (when (js2-match-token js2-RC) - (setq end (js2-current-token-end)) - (setq len (- end beg)) - (when dont-consume-rc - (js2-unget-token)) - (if check-for-comments (rjsx-maybe-message "Checking for comments between %d and %d" beg end)) - (unless (and check-for-comments - (dolist (comment js2-scanned-comments) - (rjsx-maybe-message "Comment at %d, length=%d" - (js2-node-pos comment) - (js2-node-len comment)) - ;; TODO: IF comments are in reverse document order, we should be able to - ;; bail out early and know we didn't find one - (when (and (>= (js2-node-pos comment) beg) - (<= (+ (js2-node-pos comment) (js2-node-len comment)) end)) - (cl-return-from rjsx-check-for-empty-curlies - (make-js2-empty-expr-node :pos beg :len (- end beg)))))) - (if warning - (progn (js2-report-warning "msg.empty.expr" nil beg len) - (make-js2-empty-expr-node :pos beg :len (- end beg))) - (js2-report-error "msg.empty.expr" nil beg len) - (make-js2-error-node :pos beg :len len)))))) - - -(defun rjsx-parse-spread () - "Parse an {...props} attribute." - (let ((pn (make-rjsx-spread :pos (js2-current-token-beg))) - (beg (js2-current-token-beg)) - missing-dots expr) - (setq missing-dots (not (js2-match-token js2-TRIPLEDOT))) - ;; parse-assign-expr will go crazy if we're looking at `} /', so we - ;; check for an empty spread first - (if (js2-match-token js2-RC) - (setq expr (make-js2-error-node :len 1)) - (setq expr (js2-parse-assign-expr)) - (when (js2-error-node-p expr) - (pop js2-parsed-errors))) ; We'll add our own error - (unless (or (js2-match-token js2-RC) (js2-error-node-p expr)) - (js2-report-error "msg.no.rc.after.spread" nil - beg (- (js2-current-token-end) beg))) - (setf (rjsx-spread-expr pn) expr) - (setf (js2-node-len pn) (- (js2-current-token-end) (js2-node-pos pn))) - (js2-node-add-children pn expr) - (if (js2-error-node-p expr) - (js2-report-error "msg.syntax" nil beg (- (js2-current-token-end) beg)) - (when missing-dots - (js2-report-error "msg.no.dots.in.prop.spread" nil beg (js2-node-len pn)))) - (if (= 0 (js2-node-len pn)) ; TODO: Is this ever possible? - (make-js2-error-node :pos beg :len 0) - pn))) - -(defun rjsx-parse-single-attr () - "Parse an 'a=b' JSX attribute and return the corresponding XML node." - (let ((pn (make-rjsx-attr)) name value beg) - (setq name (rjsx-parse-identifier 'rjsx-attr)) ; Won't consume token on error - (if (js2-error-node-p name) - name - (setf (rjsx-attr-name pn) name) - (setq beg (js2-node-pos name)) - (setf (js2-node-pos pn) beg) - (js2-node-add-children pn name) - (rjsx-maybe-message "Got the name for the attr: `%s'" (rjsx-identifier-full-name name)) - (if (js2-match-token js2-ASSIGN) ; Won't consume on error - (progn - (rjsx-maybe-message "Matched the equals sign") - (if (js2-match-token js2-LC) - (setq value (rjsx-parse-wrapped-expr nil t)) - (if (js2-match-token js2-STRING) - (setq value (rjsx-parse-string)) - (js2-report-error "msg.no.value.after.jsx.prop" (rjsx-identifier-full-name name) - beg (- (js2-current-token-end) beg)) - (setq value (make-js2-error-node :pos beg :len (js2-current-token-len)))))) - (setq value (make-js2-empty-expr-node :pos (js2-current-token-end) :len 0))) - (rjsx-maybe-message "value type: `%s'" (js2-node-type value)) - (setf (rjsx-attr-value pn) value) - (setf (js2-node-len pn) (- (js2-node-end value) (js2-node-pos pn))) - (js2-node-add-children pn value) - (rjsx-maybe-message "Finished single attribute.") - pn))) - -(defun rjsx-parse-wrapped-expr (allow-empty skip-to-rc) - "Parse a curly-brace-wrapped JS expression. -If ALLOW-EMPTY is non-nil, will warn for empty braces, otherwise -will signal a syntax error. If it does not find a right curly -and SKIP-TO-RC is non-nil, after the expression, consumes tokens -until the end of the JSX node" - (rjsx-maybe-message "parsing wrapped expression") - (let (pn - (beg (js2-current-token-beg)) - (child (rjsx-check-for-empty-curlies nil - :check-for-comments allow-empty - :warning allow-empty))) - (if child - (if allow-empty - (make-rjsx-wrapped-expr :pos beg :len (js2-node-len child) :child child) - child) ;; Will be an error node in this case - (setq child (js2-parse-assign-expr)) - (rjsx-maybe-message "parsed expression, type: `%s'" (js2-node-type child)) - (setq pn (make-rjsx-wrapped-expr :pos beg :child child)) - (js2-node-add-children pn child) - (when (js2-error-node-p child) - (pop js2-parsed-errors)) ; We'll record our own message after checking for RC - (if (js2-match-token js2-RC) - (rjsx-maybe-message "matched } after expression") - (rjsx-maybe-message "did not match } after expression") - (when skip-to-rc - (while (not (memql (js2-get-token) (list js2-RC js2-EOF js2-DIV js2-GT))) - (rjsx-maybe-message "Skipped over `%s'" (js2-current-token-string))) - (when (memq (js2-current-token-type) (list js2-DIV js2-GT)) - (js2-unget-token))) - (unless (js2-error-node-p child) - (js2-report-error "msg.no.rc.after.expr" nil beg - (- (js2-current-token-beg) beg)))) - (when (js2-error-node-p child) - (js2-report-error "msg.syntax" nil beg (- (js2-current-token-end) beg))) - (setf (js2-node-len pn) (- (js2-current-token-end) beg)) - pn))) - -(defun rjsx-parse-string () - "Verify that current token is a valid JSX string. -Returns a `js2-error-node' if TOKEN-STRING is not a valid JSX -string, otherwise returns a `js2-string-node'. (Strings are -invalid if they contain the delimiting quote character inside)" - (rjsx-maybe-message "Parsing string") - (let* ((token (js2-current-token)) - (beg (js2-token-beg token)) - (len (- (js2-token-end token) beg)) - (token-string (js2-token-string token)) ;; JS2 does not include the quote-chars - (quote-char (char-before (js2-token-end token)))) - (if (cl-position quote-char token-string) - (progn - (js2-report-error "msg.invalid.jsx.string" nil beg len) - (make-js2-error-node :pos beg :len len)) - (make-js2-string-node :pos beg :len len :value token-string)))) - -(cl-defun rjsx-parse-identifier (&optional face &key (allow-ns t)) - "Parse a possibly namespaced identifier and fontify with FACE if given. -Returns a `js2-error-node' if unable to parse. If the &key -argument ALLOW-NS is nil, does not allow namespaced names." - (if (js2-must-match-name "msg.bad.jsx.ident") - (let ((pn (make-rjsx-identifier)) - (beg (js2-current-token-beg)) - (name-parts (list (js2-current-token-string))) - (allow-colon allow-ns) - (continue t) - (prev-token-end (js2-current-token-end)) - (name-start (js2-current-token-beg)) - matched-colon) - (while (and continue - (or (and (memq (js2-peek-token) (list js2-SUB js2-ASSIGN_SUB)) - (prog2 ; Ensure no whitespace between previous name and this dash - (js2-get-token) - (eq prev-token-end (js2-current-token-beg)) - (js2-unget-token))) - (and allow-colon (= (js2-peek-token) js2-COLON)))) - (if (setq matched-colon (js2-match-token js2-COLON)) - (setf (rjsx-identifier-namespace pn) (apply #'concat (nreverse name-parts)) - allow-colon nil - name-parts (list) - name-start nil) - (when (= (js2-get-token) js2-ASSIGN_SUB) ; Otherwise it's a js2-SUB - (setf (js2-token-end (js2-current-token)) (1- (js2-current-token-end)) - (js2-token-type (js2-current-token)) js2-SUB - (js2-token-string (js2-current-token)) "-" - js2-ts-cursor (1+ (js2-current-token-beg)) - js2-ti-lookahead 0)) - (push "-" name-parts)) - (setq prev-token-end (js2-current-token-end)) - (if (js2-match-token js2-NAME) - (if (eq prev-token-end (js2-current-token-beg)) - (progn (push (js2-current-token-string) name-parts) - (setq prev-token-end (js2-current-token-end) - name-start (or name-start (js2-current-token-beg)))) - (js2-unget-token) - (setq continue nil)) - (when (= js2-COLON (js2-current-token-type)) - (js2-report-error "msg.bad.jsx.ident" nil beg (- (js2-current-token-end) beg))) - ;; We only keep going if this is an `ident-ending-with-dash-colon:' - (setq continue (and (not matched-colon) (= (js2-peek-token) js2-COLON))))) - (when face - (js2-set-face beg (js2-current-token-end) face 'record)) - (let ((name-node (if name-start - (make-js2-name-node :pos name-start - :len (- (js2-current-token-end) name-start) - :name (apply #'concat (nreverse name-parts))) - (make-js2-name-node :pos (js2-current-token-end) :len 0 :name "")))) - (setf (js2-node-len pn) (- (js2-current-token-end) beg) - (rjsx-identifier-name pn) name-node) - (js2-node-add-children pn name-node)) - pn) - (make-js2-error-node :len (js2-current-token-len)))) - -(defun rjsx-parse-member-or-ns (&optional face) - "Parse a dotted expression or a namespaced identifier and fontify with FACE if given." - (let ((ident (rjsx-parse-identifier face))) - (cond - ((js2-error-node-p ident) ident) - ((rjsx-identifier-namespace ident) ident) - (t (rjsx-parse-member ident face))))) - -(defun rjsx-parse-member (ident &optional face) - "Parse a dotted member expression starting with IDENT and fontify with FACE. -IDENT is the `rjsx-identifier' node for the first item in the -member expression. Returns a `js2-error-node' if unable to -parse." - (let (idents dots-pos pn end) - (setq pn (make-rjsx-member :pos (js2-node-pos ident))) - (setq end (js2-current-token-end)) - (push ident idents) - (while (and (js2-match-token js2-DOT) (not (js2-error-node-p ident))) - (push (js2-current-token-beg) dots-pos) - (setq end (js2-current-token-end)) - (setq ident (rjsx-parse-identifier nil :allow-ns nil)) - (push ident idents) - (unless (js2-error-node-p ident) - (setq end (js2-current-token-end))) - (js2-node-add-children pn ident)) - (apply 'js2-node-add-children pn idents) - (setf (rjsx-member-idents pn) (nreverse idents) - (rjsx-member-dots-pos pn) (nreverse dots-pos) - (js2-node-len pn) (- end (js2-node-pos pn))) - (when face - (js2-set-face (js2-node-pos pn) end face 'record)) - pn)) - - -(defun rjsx-parse-child (expect-fragment) - "Parse an XML child node. -Child nodes include plain (unquoted) text, other XML elements, -and {}-bracketed expressions. Return the parsed child. - -EXPECT-FRAGMENT if t, indicates that `</>' should be parsed -as a fragment closing node, and not as an empty tag." - (let ((tt (rjsx-get-next-xml-token))) - (rjsx-maybe-message "child type `%s'" tt) - (cond - ((= tt js2-LT) - (rjsx-maybe-message "xml-or-close") - (rjsx-parse-xml-or-closing-tag expect-fragment)) - - ((= tt js2-LC) - (rjsx-maybe-message "parsing expression { %s" (js2-peek-token)) - (rjsx-parse-wrapped-expr t nil)) - - ((= tt rjsx-JSX-TEXT) - (rjsx-maybe-message "text node: '%s'" (js2-current-token-string)) - (js2-set-face (js2-current-token-beg) (js2-current-token-end) 'rjsx-text 'record) - (js2-record-text-property (js2-current-token-beg) (js2-current-token-end) - 'syntax-table rjsx-text-syntax-table) - (make-rjsx-text :value (js2-current-token-string))) - - ((= tt js2-ERROR) - (make-js2-error-node :len (js2-current-token-len))) - - (t (error "Unexpected token type: %s" (js2-peek-token)))))) - -(defun rjsx-parse-xml-or-closing-tag (expect-fragment) - "Parse a JSX tag, which could be a child or a closing tag. -Return the parsed child, which is a `rjsx-closing-tag' if a -closing tag was parsed. - -EXPECT-FRAGMENT if t, indicates that `</>' should be parsed -as a fragment closing node, and not as an empty tag." - (let ((beg (js2-current-token-beg)) pn) - (rjsx-record-token-class '<) - (rjsx-record-tag-bracket-face) - (if (and (not expect-fragment) (setq pn (rjsx-parse-empty-tag))) - pn - (if (js2-match-token js2-DIV) - (progn (rjsx-record-tag-bracket-face) - (if (and expect-fragment (eq (js2-peek-token) js2-GT)) - (setq pn (make-rjsx-closing-tag :pos beg)) - (setq pn (make-rjsx-closing-tag :pos beg - :name (rjsx-parse-member-or-ns 'rjsx-tag))) - (js2-node-add-children pn (rjsx-closing-tag-name pn))) - (when (js2-must-match js2-GT "msg.no.gt.in.closer" beg (- (js2-current-token-end) beg)) - (rjsx-record-token-class '>) - (rjsx-record-tag-bracket-face)) - (setf (js2-node-len pn) (- (js2-current-token-end) beg)) - pn) - (rjsx-maybe-message "parsing a child XML item") - (rjsx-parse-xml))))) - -(defun rjsx-get-next-xml-token () - "Scan through the XML text and push one token onto the stack." - (setq js2-ts-string-buffer nil) ; for recording the text - (when (> js2-ti-lookahead 0) - (setq js2-ts-cursor (js2-current-token-end)) - (setq js2-ti-lookahead 0)) - - (let ((token (js2-new-token 0)) - c) - (rjsx-maybe-message "Running the xml scanner") - (catch 'return - (while t - (setq c (js2-get-char)) - (rjsx-maybe-message "'%s' (%s)" (if (= c js2-EOF_CHAR) "EOF" (char-to-string c)) c) - (cond - ((or (= c ?}) (= c ?>)) - (js2-set-string-from-buffer token) - (setf (js2-token-type token) js2-ERROR) - (js2-report-scan-error "msg.syntax" t) - (throw 'return js2-ERROR)) - - ((or (= c ?<) (= c ?{)) - (js2-unget-char) - (if js2-ts-string-buffer - (progn - (js2-set-string-from-buffer token) - (setf (js2-token-type token) rjsx-JSX-TEXT) - (rjsx-maybe-message "created rjsx-JSX-TEXT token: `%s'" (js2-token-string token)) - (throw 'return rjsx-JSX-TEXT)) - (js2-get-char) - (js2-set-string-from-buffer token) - (setf (js2-token-type token) (if (= c ?<) js2-LT js2-LC)) - (setf (js2-token-string token) (string c)) - (throw 'return (js2-token-type token)))) - - ((= c js2-EOF_CHAR) - (js2-set-string-from-buffer token) - (rjsx-maybe-message "Hit EOF. Current buffer: `%s'" (js2-token-string token)) - (setf (js2-token-type token) js2-ERROR) - (rjsx-maybe-message "Scanner hit EOF. Panic!") - (signal 'rjsx-eof-while-parsing nil)) - (t (js2-add-to-string c))))))) - -(js2-deflocal rjsx-buffer-chars-modified-tick 0 "Variable holding the last per-buffer value of `buffer-chars-modified-tick'.") - -(defun rjsx-maybe-reparse () - "Called before accessing the parse tree. -For small buffers, will do an immediate reparse to ensure the -parse tree is up to date." - (when (and (<= (point-max) rjsx-max-size-for-frequent-reparse) - (/= rjsx-buffer-chars-modified-tick (buffer-chars-modified-tick))) - (js2-reparse) - (setq rjsx-buffer-chars-modified-tick (buffer-chars-modified-tick)))) - -(defun rjsx--tag-at-point () - "Return the JSX tag at point, if any, or nil." - (rjsx-maybe-reparse) - (let ((node (js2-node-at-point (point) t))) - (while (and node (not (rjsx-node-p node))) - (setq node (js2-node-parent node))) - node)) - - -;;;; Interactive commands and keybindings -(defun rjsx-electric-lt (n) - "Insert a context-sensitive less-than sign. -Optional prefix argument N indicates how many signs to insert. -If N is greater than one, no special handling takes place. -Otherwise, if the less-than sign would start a JSX block, it -inserts `</>' and places the cursor inside the new tag." - (interactive "p") - (if (/= n 1) - (insert (make-string n ?<)) - (if (save-excursion - (forward-comment most-negative-fixnum) - (skip-chars-backward "\n\r") - (or (= (point) (point-min)) - (memq (char-before) (append "=(?:>}&|{," nil)) - (let ((start (- (point) 6))) - (and (>= start (point-min)) - (string= (buffer-substring start (point)) "return"))))) - (progn (insert "</>") - (backward-char 2)) - (insert "<")))) - -(define-key rjsx-mode-map "<" 'rjsx-electric-lt) - -(defun rjsx-expand-self-closing-tag (node) - "Expand NODE into a balanced tag. -Assumes NODE is self-closing `rjsx-node', and that point is at -the self-closing slash." - (delete-char 1) - (search-forward ">") - (save-excursion - (insert "</" (rjsx-node-opening-tag-name node) ">"))) - -(defun rjsx-electric-gt (n) - "Insert a context-sensitive greater-than sign. -Optional prefix argument N indicates how many signs to insert. -If N is greater than one, no special handling takes place. -Otherwise, if point is in a self-closing JSX tag just before the -slash, it creates a matching end-tag and places point just inside -the tags." - (interactive "p") - (if (or (/= n 1) - (not (eq (get-char-property (point) 'rjsx-class) 'self-closing-slash))) - (insert (make-string n ?>)) - (let ((node (rjsx--tag-at-point))) - (if node - (rjsx-expand-self-closing-tag node) - (insert (make-string n ?>)))))) - -(define-key rjsx-mode-map ">" 'rjsx-electric-gt) - -(defun rjsx-delete-creates-full-tag (n &optional killflag) - "N and KILLFLAG are as in `delete-char'. -If N is 1 and KILLFLAG nil, checks to see if we're in a -self-closing tag about to delete the slash. If so, deletes the -slash and inserts a matching end-tag." - (interactive "p") - (if (or killflag (/= 1 n) (not (eq (get-char-property (point) 'rjsx-class) 'self-closing-slash))) - (if (called-interactively-p 'any) - (call-interactively 'delete-forward-char) - (delete-char n killflag)) - (let ((node (rjsx--tag-at-point))) - (if node - (rjsx-expand-self-closing-tag node) - (delete-char 1))))) - -(define-key rjsx-mode-map (kbd "C-d") 'rjsx-delete-creates-full-tag) - -(defun rjsx-rename-tag-at-point (new-name) - "Prompt for a new name and modify the tag at point. -NEW-NAME is the name to give the tag." - (interactive "sNew tag name: ") - (let* ((tag (rjsx--tag-at-point)) - (closer (and tag (rjsx-node-closing-tag tag)))) - (cond - ((null tag) (message "No JSX tag found at point")) - ((null (rjsx-node-name tag)) ; fragment - (cl-assert closer nil "Fragment has no closing-tag") - (save-excursion - (goto-char (+ 2 (js2-node-abs-pos closer))) - (insert new-name) - (goto-char (1+ (js2-node-abs-pos tag))) - (insert new-name)) - (js2-reparse)) - (t - (let* ((head (rjsx-node-name tag)) - (tail (when closer (rjsx-closing-tag-name closer))) - beg end) - (dolist (part (if tail (list tail head) (list head))) - (setq beg (js2-node-abs-pos part) - end (+ beg (js2-node-len part))) - (delete-region beg end) - (save-excursion (goto-char beg) (insert new-name))) - (js2-reparse)))))) - -(define-key rjsx-mode-map (kbd "C-c C-r") 'rjsx-rename-tag-at-point) - - - -;; Utilities - -(defun rjsx-ancestor (node predicate) - "Find an ancestor of NODE satisfying PREDICATE. - -Search upwards from the parent of NODE for an ancestor where -PREDICATE returns t. Returns nil if no ancestor satisfies -PREDICATE." - (let ((ancestor (js2-node-parent node))) - (while (and ancestor - (not (funcall predicate ancestor))) - (setq ancestor (js2-node-parent ancestor))) - ancestor)) - -(cl-defun rjsx--prev-sibling (node) - "Get the previous non-blank sibling of NODE." - (let* ((parent (js2-node-parent node)) prev) - (dolist (kid (rjsx-node-kids parent)) - (cond - ((eq kid node) (cl-return-from rjsx--prev-sibling prev)) - ((and (rjsx-text-p kid) (string-blank-p (rjsx-text-value kid)))) - (t (setq prev kid)))))) - - - -;; Comment handling - -(defun rjsx-comment-region-function (beg end &optional arg) - (js2-mode-wait-for-parse - (lambda () - (let* ((node (js2-node-at-point beg)) - (in-jsx (or (rjsx-node-p node) - (rjsx-ancestor node 'rjsx-node-p))) - (use-jsx-comment (and (rjsx-node-p (js2-node-parent node)) - (or (rjsx-text-p node) - (and (rjsx-node-p node) - (= (js2-node-abs-pos node) beg)))))) - (cond (use-jsx-comment - (let ((comment-start "{/*") - (comment-end "*/}")) - (comment-normalize-vars) - (comment-region-default beg end arg))) - (in-jsx - (let ((comment-start "/*") - (comment-end "*/")) - (comment-normalize-vars) - (if (rjsx-wrapped-expr-p node) - (if (js2-empty-expr-node-p (rjsx-wrapped-expr-child node)) - (let ((comment-start "{/*") - (comment-end "*/}")) - (comment-normalize-vars) - (comment-region-default beg end arg)) - (comment-region-default (1+ beg) (1- end) arg)) - (comment-region-default beg end arg)))) - (t (comment-region-default beg end arg))))))) - -(defun rjsx-maybe-unwrap-expr (beg end) - (save-excursion - (save-restriction - (js2-reparse) - (goto-char beg) - (skip-chars-forward "[:space:]\n" end) - (let* ((node (js2-node-at-point (point))) - (parent (js2-node-parent node))) - (when (and parent - (rjsx-wrapped-expr-p parent) - (rjsx-node-p (js2-node-parent parent)) - (or (rjsx-text-p node) (rjsx-node-p node))) - (let* ((expr-start (js2-node-abs-pos parent)) - (expr-end (+ expr-start (js2-node-len parent))) - (body-start (1+ expr-start)) - (body-end (1- expr-end)) - (body-length (- body-end body-start))) - (when (and (comment-only-p body-start beg) - (comment-only-p end body-end)) - (goto-char expr-start) - (delete-char 1) - (forward-char body-length) - (delete-char 1)))))))) - -(defun rjsx-uncomment-region-function (beg end &optional _) - (js2-mode-wait-for-parse - (lambda () - (goto-char beg) - (setq end (copy-marker end)) - (let (cs ts te ce matched-start) - ;; find comment start - (while (and (<= (point) end) - (setq matched-start - (and (re-search-forward comment-start-skip end t 1) - (match-string-no-properties 0)))) - ;; delete comment-start - (setq cs (match-beginning 1)) - (setq ts (match-end 1)) - (goto-char cs) - (delete-region cs ts) - - ;; delete comment-padding start - (when (and comment-padding (looking-at (regexp-quote comment-padding))) - (delete-region (point) (+ (point) (length comment-padding)))) - - ;; find comment end - (when (re-search-forward (if (string-match "//+" matched-start) "\n" "\\*/}?") end t 1) - (setq te (or (match-beginning 1) (match-beginning 0))) - (setq ce (or (match-end 1) (match-end 0))) - (goto-char te) - - ;; delete commend-end if it's not a newline - (unless (string= "\n" (match-string-no-properties 0)) - (delete-region te ce) - - ;; delete comment-padding end - (when comment-padding - (backward-char (length comment-padding)) - (when (looking-at (regexp-quote comment-padding)) - (delete-region (point) (+ (point) (length comment-padding)))))) - - ;; unescape inner comments if any - (save-restriction - (narrow-to-region cs (point)) - (comment-quote-nested "{/*" "*/}" t))))) - - (rjsx-maybe-unwrap-expr beg end) - - (set-marker end nil)))) - -(defun rjsx-comment-quote-nested-function (_ __ unp) - (let ((re (concat "\\*\\(\\\\" (if unp "+" "*") "\\)/}?" - "\\|" - "{?/\\(\\\\" (if unp "+" "*") "\\)\\*"))) - (goto-char (point-min)) - (while (re-search-forward re (point-max) t 1) - (let ((ceme (match-end 1)) - (csme (match-end 2))) - (goto-char (or ceme csme)) - (if (and unp (>= (length (or (match-string-no-properties 1) - (match-string-no-properties 2))) - 1)) - (delete-char -1) - (insert "\\")))))) - -;;;###autoload -(defun rjsx-comment-dwim (arg) - "RJSX implementation of `comment-dwim'. If called on a region, -this function delegates to `comment-or-uncomment-region'. If the -point is not in a JSX context, it delegates to the -`comment-dwim', otherwise it will comment the JSX AST node at -point using the apppriate comment delimiters. - -For example: If point is on a JSX attribute or JSX expression, it -will comment the entire attribute using \"/* */\". , otherwise if -it's on a descendent JSX Element, it will use \"{/* */}\" -instead." - (interactive "*P") - (js2-mode-wait-for-parse - (lambda () - (if (use-region-p) - (comment-or-uncomment-region (region-beginning) (region-end) arg) - (save-excursion - (when (looking-at "[[:space:]]") - (forward-whitespace 1)) - (let ((node (js2-node-at-point))) - (cond - ;; If inside a regular JS comment node, uncomment the node - ((js2-comment-at-point) - (uncomment-region (js2-node-abs-pos node) (js2-node-abs-end node))) - ;; If looking at a commented JSXAttribute value, forward one char to - ;; uncomment the body - ((and (looking-at comment-start-skip) - (looking-at "{") - (rjsx-attr-p (js2-node-parent node))) - (forward-char 1) - (rjsx-comment-dwim arg)) - ;; If the entire line is a comment, uncomment it - ((and (comment-only-p (point) (line-end-position)) - (not (looking-at "[[:space:]]*$"))) - (uncomment-region (point) (line-end-position))) - ;; If looking at JSXText, comment the current line - ((rjsx-text-p node) - (let ((comment-start "{/*") - (comment-end "*/}")) - (comment-line 1))) - ;; If looking at a JSXAttribute or a JSXSpreadAttribute, comment the - ;; entire attribute with C-style comment - ((or (rjsx-spread-p node) - (rjsx-ancestor node 'rjsx-spread-p) - (rjsx-attr-p node) - (and (js2-name-node-p node) - (rjsx-identifier-p (js2-node-parent node)) - (rjsx-attr-p (js2-node-parent (js2-node-parent node)))) - (and (rjsx-identifier-p node) - (rjsx-attr-p (js2-node-parent node))) - (and (js2-string-node-p node) - (rjsx-attr-p (js2-node-parent node)))) - (let ((node (or (and (rjsx-spread-p node) node) - (rjsx-ancestor node 'rjsx-spread-p) - (and (rjsx-attr-p node) node) - (rjsx-ancestor node 'rjsx-attr-p))) - (comment-start "/*") - (comment-end "*/")) - (comment-region - (js2-node-abs-pos node) - (js2-node-abs-end node) arg))) - ;; If looking at a JSXElement or JSXFragment, comment the entire - ;; node with JSX comment if it's a child of one of the above, - ;; otherwise just comment with C-style comment. - ((or (rjsx-node-p node) - (rjsx-closing-tag-p node) - (rjsx-member-p node) - (rjsx-ancestor node 'rjsx-member-p)) - (let* ((node (or (and (rjsx-node-p node) node) - (rjsx-ancestor node 'rjsx-node-p))) - (parent-node-p (rjsx-node-p (js2-node-parent node))) - (closing (rjsx-node-closing-tag node)) - (comment-start (if parent-node-p "{/*" "/*")) - (comment-end (if parent-node-p "*/}" "*/"))) - (comment-region - (js2-node-abs-pos node) - (js2-node-abs-end (or closing node)) arg))) - ;; If looking at a JSX {expression} or is inside a JSX expression, - ;; comment the body with regular C-style comment. If the body is - ;; already commented, uncomment it. If on a multi line JSX - ;; expression, just comment the line. - ((or (rjsx-wrapped-expr-p node) - (rjsx-ancestor node 'rjsx-wrapped-expr-p)) - (let* ((expr (or (and (rjsx-wrapped-expr-p node) node) - (rjsx-ancestor node 'rjsx-wrapped-expr-p))) - ;; Can only happen as a child of an element or fragment, an - ;; empty JSX expression attribute value will result in an - ;; error node - (expr-empty (js2-empty-expr-node-p (rjsx-wrapped-expr-child expr))) - (body-start (1+ (js2-node-abs-pos expr))) - (body-end (1- (js2-node-abs-end expr))) - (expr-child-of-node (rjsx-node-p (js2-node-parent expr)))) - ;; If the body is all comment, uncomment it, otherwise if it's - ;; empty, wrap it with a JSX comment - (if (and expr-child-of-node expr-empty) - (if (or (= (1+ (js2-node-abs-pos expr)) (js2-node-abs-end expr)) ;; {} - (string-blank-p (buffer-substring-no-properties body-start body-end))) - (let ((comment-start "{/*") - (comment-end "*/}")) - (comment-region (js2-node-abs-pos expr) (js2-node-abs-end expr) arg)) - (when (comment-only-p body-start body-end) - (uncomment-region body-start body-end arg))) - ;; If in a multi-line JSX expression, comment the line - (if (> (count-lines body-start body-end) 1) - (comment-dwim arg) - ;; Otherwise comment the entire body - (let ((comment-start "/*") - (comment-end "*/")) - (comment-region body-start body-end arg)))))) - ;; Otherwise just delegate to (comment-dwim) - (t (comment-dwim arg))))))))) - -(define-key rjsx-mode-map [remap comment-dwim] 'rjsx-comment-dwim) - - - -;; Indentation - -(defun rjsx--js--looking-at-operator-p-advice (orig-fun) - "Advice for `js--looking-at-operator-p' (ORIG-FUN) to handle JSX properly." - (if (memq (get-char-property (point) 'rjsx-class) '(< >)) - nil - (apply orig-fun nil))) - -(advice-add 'js--looking-at-operator-p :around #'rjsx--js--looking-at-operator-p-advice) - -(defvar-local rjsx--indent-region-p nil - "t when `indent-region' is running.") - -(defvar-local rjsx--indent-running-offset 0 - "Running offset to add to the node POS at the beginning of -every line during `indent-region' so we don't have to reparse -after indenting every line to update the AST node positions.") - -(defvar-local rjsx--node-abs-pos-cache nil - "Cache for JSX nodes' indent levels. -Used during `indent-region' calls to avoid repeated -`js2-node-abs-pos' calls.") - -(defun rjsx--node-abs-pos (node) - "Caching version of `js2-node-abs-pos' for NODE." - (if (null rjsx--node-abs-pos-cache) - (js2-node-abs-pos node) - (let ((cached (gethash node rjsx--node-abs-pos-cache))) - (or cached - (setf (gethash node rjsx--node-abs-pos-cache) - (js2-node-abs-pos node)))))) - -(defsubst rjsx--node-indent-level (node) - "Return the indent level for NODE." - (save-excursion (goto-char (rjsx--node-abs-pos node)) (current-column))) - -(defsubst rjsx--indent-line-to-offset (node offset) - "Indent current line relative to NODE, which must be an `rjsx-node' instance. -OFFSET indicates the number of spaces to add." - (indent-line-to - (+ offset (rjsx--node-indent-level node)))) - -(defun rjsx-indent-line () - "Similar to `js-jsx-indent-line', but fixes indentation bug -with JSXElement after a JSX expression and arrow function. In -addition, the > of a multi-line open tag and the /> of a -multi-line self-closing tag are aligned to the beginning <. This -function also ensures everything inside a JSX context is indented -according to `js-indent-level' using spaces, this is due to the -limitation of `sgml-indent-line' not being able to indent with -tabs. - -Fixes: -- https://github.com/mooz/js2-mode/issues/490 -- https://github.com/mooz/js2-mode/issues/482 -- https://github.com/mooz/js2-mode/issues/462 -- https://github.com/mooz/js2-mode/issues/451 -" - (unless rjsx--indent-region-p - (js2-reparse)) - - (let* ((indent-tabs-mode nil) - (cur-pos (save-excursion (back-to-indentation) (point))) - (cur-char (char-after cur-pos)) - (node (js2-node-at-point (- cur-pos rjsx--indent-running-offset))) - (parent (js2-node-parent node))) - (cond - ((rjsx-node-p node) - (cond - ((eq cur-char ?<) - (if (rjsx-node-p parent) - (rjsx--indent-line-to-offset parent sgml-basic-offset) - ;; Top-level node, indent as JS - (js-indent-line)) - (when rjsx--node-abs-pos-cache - (setf (gethash node rjsx--node-abs-pos-cache) - (save-excursion (back-to-indentation) (point))))) - ((memq cur-char '(?/ ?>)) - (rjsx--indent-line-to-offset node 0)) - ((eq cur-char ?\n) - (rjsx--indent-line-to-offset node sgml-basic-offset)) - (t (error "Don't know how to indent %s for JSX node" (make-string 1 cur-char))))) - ((and (rjsx-identifier-p parent) - (rjsx-member-p (js2-node-parent parent)) - (rjsx-node-p (js2-node-parent (js2-node-parent parent)))) - (rjsx--indent-line-to-offset (js2-node-parent (js2-node-parent parent)) 0)) - - ;; JSX children - ((rjsx-closing-tag-p node) - (rjsx--indent-line-to-offset parent 0)) - ((rjsx-text-p node) - (rjsx--indent-line-to-offset parent sgml-basic-offset)) - ((rjsx-wrapped-expr-p node) - (if (eq cur-char ?}) - (js-indent-line) - (rjsx--indent-line-to-offset parent sgml-basic-offset))) - - ;; Attribute-like (spreads, attributes, etc.) - ;; if first attr is on same line as tag, then align - ;; otherwise indent to parent level + sgml-basic-offset - ((or (rjsx-identifier-p node) - (and (rjsx-identifier-p parent) - (rjsx-attr-p (js2-node-parent parent))) - (rjsx-spread-p node)) - (let* ((tag (or (rjsx-ancestor node #'rjsx-node-p) - (error "Did not find containing JSX tag for attributes"))) - (name (rjsx-node-name tag)) - column) - (save-excursion - (goto-char (rjsx--node-abs-pos tag)) - (setq column (current-column)) - (when name (forward-char (js2-node-end name)) (skip-chars-forward " \t")) - (if (eolp) - (setq column (+ column sgml-basic-offset sgml-attribute-offset)) - (setq column (current-column)))) - (indent-line-to column))) - - ;; Everything else indent as javascript - (t (js-indent-line))) - - (when rjsx--indent-region-p - (cl-incf rjsx--indent-running-offset - (- (save-excursion (back-to-indentation) (point)) - cur-pos))))) - -(defun rjsx-indent-region (start end) - "Indent the region from START to END as JS/JSX." - (js2-reparse) - (let ((rjsx--indent-region-p t) - (rjsx--indent-running-offset 0) - (rjsx--node-abs-pos-cache (make-hash-table))) - (js2-indent-region start end))) - - -(provide 'rjsx-mode) -;;; rjsx-mode.el ends here - -;; Local Variables: -;; outline-regexp: ";;;\\(;* [^ -;; ]\\|###autoload\\)\\|(....." -;; End: diff --git a/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode.elc b/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode.elc deleted file mode 100644 index 6d39dc917bc8..000000000000 --- a/configs/shared/emacs/.emacs.d/elpa/rjsx-mode-20180823.1645/rjsx-mode.elc +++ /dev/null Binary files differ |