]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/js.el
* lisp/emacs-lisp/nadvice.el (advice--member-p): Return the advice if found.
[gnu-emacs] / lisp / progmodes / js.el
index d954cd53e0a12d6ccca35b24bbdda9a51e096438..2ea78fc321c31a26fd1d2de05e0a8ae14e276363 100644 (file)
@@ -1,6 +1,6 @@
 ;;; js.el --- Major mode for editing JavaScript  -*- lexical-binding: t -*-
 
-;; Copyright (C) 2008-2012 Free Software Foundation, Inc.
+;; Copyright (C) 2008-2013 Free Software Foundation, Inc.
 
 ;; Author: Karl Landstrom <karl.landstrom@brgeight.se>
 ;;         Daniel Colascione <dan.colascione@gmail.com>
@@ -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-syntax-backward ".")
+                                     (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)