diff options
Diffstat (limited to 'lisp/progmodes/js.el')
-rw-r--r-- | lisp/progmodes/js.el | 121 |
1 files changed, 77 insertions, 44 deletions
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el index a16bac7a6cd..4aa1ac270d5 100644 --- a/lisp/progmodes/js.el +++ b/lisp/progmodes/js.el @@ -1680,12 +1680,15 @@ This performs fontification according to `js--class-styles'." "each")) "Regexp matching keywords optionally followed by an opening brace.") +(defconst js--declaration-keyword-re + (regexp-opt '("var" "let" "const") 'words) + "Regular expression matching variable declaration keywords.") + (defconst js--indent-operator-re (concat "[-+*/%<>=&^|?:.]\\([^-+*/]\\|$\\)\\|" (js--regexp-opt-symbol '("in" "instanceof"))) "Regexp matching operators that affect indentation of continued expressions.") - (defun js--looking-at-operator-p () "Return non-nil if point is on a JavaScript operator, other than a comma." (save-match-data @@ -1764,6 +1767,37 @@ nil." (list (cons 'c js-comment-lineup-func)))) (c-get-syntactic-indentation (list (cons symbol anchor))))) +(defun js--multi-line-declaration-indentation () + "Helper function for `js--proper-indentation'. +Return the proper indentation of the current line if it belongs to a declaration +statement spanning multiple lines; otherwise, return nil." + (let (at-opening-bracket) + (save-excursion + (back-to-indentation) + (when (not (looking-at js--declaration-keyword-re)) + (when (looking-at js--indent-operator-re) + (goto-char (match-end 0))) + (while (and (not at-opening-bracket) + (not (bobp)) + (let ((pos (point))) + (save-excursion + (js--backward-syntactic-ws) + (or (eq (char-before) ?,) + (and (not (eq (char-before) ?\;)) + (prog2 + (skip-chars-backward "[[:punct:]]") + (looking-at js--indent-operator-re) + (js--backward-syntactic-ws)) + (not (eq (char-before) ?\;))) + (and (>= pos (point-at-bol)) + (<= pos (point-at-eol))))))) + (condition-case nil + (backward-sexp) + (scan-error (setq at-opening-bracket t)))) + (when (looking-at js--declaration-keyword-re) + (goto-char (match-end 0)) + (1+ (current-column))))))) + (defun js--proper-indentation (parse-status) "Return the proper indentation for the current line." (save-excursion @@ -1772,6 +1806,7 @@ nil." (js--get-c-offset 'c (nth 8 parse-status))) ((nth 8 parse-status) 0) ; inside string ((js--ctrl-statement-indentation)) + ((js--multi-line-declaration-indentation)) ((eq (char-after) ?#) 0) ((save-excursion (js--beginning-of-macro)) 4) ((nth 1 parse-status) @@ -1823,22 +1858,31 @@ nil." ;;; Filling +(defvar js--filling-paragraph nil) + +;; FIXME: Such redefinitions are bad style. We should try and use some other +;; way to get the same result. +(defadvice c-forward-sws (around js-fill-paragraph activate) + (if js--filling-paragraph + (setq ad-return-value (js--forward-syntactic-ws (ad-get-arg 0))) + ad-do-it)) + +(defadvice c-backward-sws (around js-fill-paragraph activate) + (if js--filling-paragraph + (setq ad-return-value (js--backward-syntactic-ws (ad-get-arg 0))) + ad-do-it)) + +(defadvice c-beginning-of-macro (around js-fill-paragraph activate) + (if js--filling-paragraph + (setq ad-return-value (js--beginning-of-macro (ad-get-arg 0))) + ad-do-it)) + (defun js-c-fill-paragraph (&optional justify) "Fill the paragraph with `c-fill-paragraph'." (interactive "*P") - ;; FIXME: Such redefinitions are bad style. We should try and use some other - ;; way to get the same result. - (cl-letf (((symbol-function 'c-forward-sws) - (lambda (&optional limit) - (js--forward-syntactic-ws limit))) - ((symbol-function 'c-backward-sws) - (lambda (&optional limit) - (js--backward-syntactic-ws limit))) - ((symbol-function 'c-beginning-of-macro) - (lambda (&optional limit) - (js--beginning-of-macro limit)))) - (let ((fill-paragraph-function 'c-fill-paragraph)) - (c-fill-paragraph justify)))) + (let ((js--filling-paragraph t) + (fill-paragraph-function 'c-fill-paragraph)) + (c-fill-paragraph justify))) ;;; Type database and Imenu @@ -3297,29 +3341,21 @@ If one hasn't been set, or if it's stale, prompt for a new one." (define-derived-mode js-mode prog-mode "Javascript" "Major mode for editing JavaScript." :group 'js + (setq-local indent-line-function 'js-indent-line) + (setq-local beginning-of-defun-function 'js-beginning-of-defun) + (setq-local end-of-defun-function 'js-end-of-defun) + (setq-local open-paren-in-column-0-is-defun-start nil) + (setq-local font-lock-defaults (list js--font-lock-keywords)) + (setq-local syntax-propertize-function #'js-syntax-propertize) - (set (make-local-variable 'indent-line-function) 'js-indent-line) - (set (make-local-variable 'beginning-of-defun-function) - 'js-beginning-of-defun) - (set (make-local-variable 'end-of-defun-function) - 'js-end-of-defun) - - (set (make-local-variable 'open-paren-in-column-0-is-defun-start) nil) - (set (make-local-variable 'font-lock-defaults) - (list js--font-lock-keywords)) - (set (make-local-variable 'syntax-propertize-function) - #'js-syntax-propertize) - - (set (make-local-variable 'parse-sexp-ignore-comments) t) - (set (make-local-variable 'parse-sexp-lookup-properties) t) - (set (make-local-variable 'which-func-imenu-joiner-function) - #'js--which-func-joiner) + (setq-local parse-sexp-ignore-comments t) + (setq-local parse-sexp-lookup-properties t) + (setq-local which-func-imenu-joiner-function #'js--which-func-joiner) ;; Comments - (set (make-local-variable 'comment-start) "// ") - (set (make-local-variable 'comment-end) "") - (set (make-local-variable 'fill-paragraph-function) - 'js-c-fill-paragraph) + (setq-local comment-start "// ") + (setq-local comment-end "") + (setq-local fill-paragraph-function 'js-c-fill-paragraph) ;; Parse cache (add-hook 'before-change-functions #'js--flush-caches t t) @@ -3329,8 +3365,7 @@ If one hasn't been set, or if it's stale, prompt for a new one." ;; Imenu (setq imenu-case-fold-search nil) - (set (make-local-variable 'imenu-create-index-function) - #'js--imenu-create-index) + (setq imenu-create-index-function #'js--imenu-create-index) ;; for filling, pretend we're cc-mode (setq c-comment-prefix-regexp "//+\\|\\**" @@ -3341,10 +3376,10 @@ If one hasn't been set, or if it's stale, prompt for a new one." c-comment-start-regexp "/[*/]\\|\\s!" comment-start-skip "\\(//+\\|/\\*+\\)\\s *") - (set (make-local-variable 'electric-indent-chars) - (append "{}():;," electric-indent-chars)) ;FIXME: js2-mode adds "[]*". - (set (make-local-variable 'electric-layout-rules) - '((?\; . after) (?\{ . after) (?\} . before))) + (setq-local electric-indent-chars + (append "{}():;," electric-indent-chars)) ;FIXME: js2-mode adds "[]*". + (setq-local electric-layout-rules + '((?\; . after) (?\{ . after) (?\} . before))) (let ((c-buffer-is-cc-mode t)) ;; FIXME: These are normally set by `c-basic-common-init'. Should @@ -3356,8 +3391,7 @@ If one hasn't been set, or if it's stale, prompt for a new one." (make-local-variable 'adaptive-fill-regexp) (c-setup-paragraph-variables)) - (set (make-local-variable 'syntax-begin-function) - #'js--syntax-begin-function) + (setq-local syntax-begin-function #'js--syntax-begin-function) ;; Important to fontify the whole buffer syntactically! If we don't, ;; then we might have regular expression literals that aren't marked @@ -3371,8 +3405,7 @@ If one hasn't been set, or if it's stale, prompt for a new one." ;; calls to syntax-propertize wherever it's really needed. (syntax-propertize (point-max))) -;;;###autoload -(defalias 'javascript-mode 'js-mode) +;;;###autoload (defalias 'javascript-mode 'js-mode) (eval-after-load 'folding '(when (fboundp 'folding-add-to-marks-list) |