]> code.delx.au - gnu-emacs/blobdiff - lisp/progmodes/js.el
SQL mode version 2.1
[gnu-emacs] / lisp / progmodes / js.el
index 0fad93224166c7b4eec4dd71f87f4c8461b4e450..6bd8fbc2442894a2a8e278e0fe40a14be64fcb4d 100644 (file)
@@ -1,6 +1,6 @@
 ;;; js.el --- Major mode for editing JavaScript
 
-;; Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
 
 ;; Author: Karl Landstrom <karl.landstrom@brgeight.se>
 ;;         Daniel Colascione <dan.colascione@gmail.com>
@@ -98,8 +98,8 @@ name.")
   (concat "^\\s-*?\\(" js--dotted-name-re "\\)\\.prototype"
           "\\.\\(" js--name-re "\\)\\s-*?=\\s-*?\\(function\\)\\_>")
   "Regexp matching an explicit JavaScript prototype \"method\" declaration.
-Group 1 is a (possibly-dotted) class name, group 2 is a method
-name, and group 3 is the 'function' keyword." )
+Group 1 is a (possibly-dotted) class name, group 2 is a method name,
+and group 3 is the 'function' keyword.")
 
 (defconst js--plain-class-re
   (concat "^\\s-*\\(" js--dotted-name-re "\\)\\.prototype"
@@ -227,14 +227,14 @@ A class definition style is a plist with the following keys:
 :name is a human-readable name of the class type
 
 :class-decl is a regular expression giving the start of the
-class. Its first group must match the name of its class. If there
-is a parent class, the second group should match, and it should
-be the name of the class.
+class.  Its first group must match the name of its class.  If there
+is a parent class, the second group should match, and it should be
+the name of the class.
 
 If :prototype is present and non-nil, the parser will merge
 declarations for this constructs with others at the same lexical
-level that have the same name. Otherwise, multiple definitions
-will create multiple top-level entries. Don't use :prototype
+level that have the same name.  Otherwise, multiple definitions
+will create multiple top-level entries.  Don't use :prototype
 unnecessarily: it has an associated cost in performance.
 
 If :strip-prototype is present and non-nil, then if the class
@@ -272,7 +272,7 @@ Match group 1 is MUMBLE.")
 (defconst js--macro-decl-re
   (concat "^\\s-*#\\s-*define\\s-+\\(" js--cpp-name-re "\\)\\s-*(")
   "Regexp matching a CPP macro definition, up to the opening parenthesis.
-Match group 1 is the name of the function.")
+Match group 1 is the name of the macro.")
 
 (defun js--regexp-opt-symbol (list)
   "Like `regexp-opt', but surround the result with `\\\\_<' and `\\\\_>'."
@@ -436,6 +436,13 @@ The value must be no less than minus `js-indent-level'."
   :type 'integer
   :group 'js)
 
+(defcustom js-auto-indent-flag t
+  "Whether to automatically indent when typing punctuation characters.
+If non-nil, the characters {}();,: also indent the current line
+in Javascript mode."
+  :type 'boolean
+  :group 'js)
+
 (defcustom js-flat-functions nil
   "Treat nested functions as top-level functions in `js-mode'.
 This applies to function movement, marking, and so on."
@@ -483,6 +490,9 @@ getting timeout messages."
 
 (defvar js-mode-map
   (let ((keymap (make-sparse-keymap)))
+    (mapc (lambda (key)
+           (define-key keymap key #'js-insert-and-indent))
+         '("{" "}" "(" ")" ":" ";" ","))
     (define-key keymap [(control ?c) (meta ?:)] #'js-eval)
     (define-key keymap [(control ?c) (control ?j)] #'js-set-js-context)
     (define-key keymap [(control meta ?x)] #'js-eval-defun)
@@ -498,6 +508,21 @@ getting timeout messages."
     keymap)
   "Keymap for `js-mode'.")
 
+(defun js-insert-and-indent (key)
+  "Run the command bound to KEY, and indent if necessary.
+Indentation does not take place if point is in a string or
+comment."
+  (interactive (list (this-command-keys)))
+  (call-interactively (lookup-key (current-global-map) key))
+  (let ((syntax (save-restriction (widen) (syntax-ppss))))
+    (when (or (and (not (nth 8 syntax))
+                   js-auto-indent-flag)
+              (and (nth 4 syntax)
+                   (eq (current-column)
+                       (1+ (current-indentation)))))
+      (indent-according-to-mode))))
+
+
 ;;; Syntax table and parsing
 
 (defvar js-mode-syntax-table
@@ -538,8 +563,8 @@ getting timeout messages."
   "Helper function for `js--update-quick-match-re'.
 If LIST contains any element that is not nil, return its non-nil
 elements, separated by SEPARATOR, prefixed by PREFIX, and ended
-with SUFFIX as with `concat'. Otherwise, if LIST is empty, return
-nil. If any element in LIST is itself a list, flatten that
+with SUFFIX as with `concat'.  Otherwise, if LIST is empty, return
+nil.  If any element in LIST is itself a list, flatten that
 element."
   (setq list (js--flatten-list list))
   (when list
@@ -793,7 +818,7 @@ determined.  Otherwise, return nil."
 (defun js--function-prologue-beginning (&optional pos)
   "Return the start of the JavaScript function prologue containing POS.
 A function prologue is everything from start of the definition up
-to and including the opening brace. POS defaults to point.
+to and including the opening brace.  POS defaults to point.
 If POS is not in a function prologue, return nil."
   (let (prologue-begin)
     (save-excursion
@@ -901,7 +926,7 @@ Return the pitem of the function we went to the beginning of."
 
 (defun js--flush-caches (&optional beg ignored)
   "Flush the `js-mode' syntax cache after position BEG.
-BEG defaults to point-min, meaning to flush the entire cache."
+BEG defaults to `point-min', meaning to flush the entire cache."
   (interactive)
   (setq beg (or beg (save-restriction (widen) (point-min))))
   (setq js--cache-end (min js--cache-end beg)))
@@ -968,8 +993,8 @@ the body of `js--ensure-cache'."
 
 (defun js--split-name (string)
   "Split a JavaScript name into its dot-separated parts.
-This also removes any prototype parts from the split name (unless
-the name is just \"prototype\" to start with)."
+This also removes any prototype parts from the split name
+\(unless the name is just \"prototype\" to start with)."
   (let ((name (save-match-data
                 (split-string string "\\." t))))
     (unless (and (= (length name) 1)
@@ -1211,12 +1236,11 @@ LIMIT defaults to point."
   "Value of `end-of-defun-function' for `js-mode'."
   (setq arg (or arg 1))
   (while (and (not (bobp)) (< arg 0))
-    (let (orig-pos (point))
-      (incf arg)
-      (js-beginning-of-defun)
-      (js-beginning-of-defun)
-      (unless (bobp)
-        (js-end-of-defun))))
+    (incf arg)
+    (js-beginning-of-defun)
+    (js-beginning-of-defun)
+    (unless (bobp)
+      (js-end-of-defun)))
 
   (while (> arg 0)
     (decf arg)
@@ -1389,8 +1413,8 @@ spec.  FUNC must preserve the match data."
 (defun js--variable-decl-matcher (limit)
   "Font-lock matcher for variable names in a variable declaration.
 This is a cc-mode-style matcher that *always* fails, from the
-point of view of font-lock. It applies highlighting directly with
-`font-lock-apply-higlight'."
+point of view of font-lock.  It applies highlighting directly with
+`font-lock-apply-highlight'."
   (condition-case nil
       (save-restriction
         (narrow-to-region (point-min) limit)
@@ -1546,7 +1570,7 @@ point of view of font-lock. It applies highlighting directly with
   "Level three font lock for `js-mode'.")
 
 (defun js--inside-pitem-p (pitem)
-  "Return whether point is inside the given pitem's header or body"
+  "Return whether point is inside the given pitem's header or body."
   (js--ensure-cache)
   (assert (js--pitem-h-begin pitem))
   (assert (js--pitem-paren-depth pitem))
@@ -1558,7 +1582,7 @@ point of view of font-lock. It applies highlighting directly with
 (defun js--parse-state-at-point ()
   "Parse the JavaScript program state at point.
 Return a list of `js--pitem' instances that apply to point, most
-specific first. In the worst case, the current toplevel instance
+specific first.  In the worst case, the current toplevel instance
 will be returned."
   (save-excursion
     (save-restriction
@@ -1596,7 +1620,7 @@ context."
   (let* ((syntactic-context (js--syntactic-context-from-pstate
                              (js--parse-state-at-point))))
 
-    (when (interactive-p)
+    (when (called-interactively-p 'interactive)
       (message "Syntactic context: %s" syntactic-context))
 
     syntactic-context))
@@ -1753,7 +1777,7 @@ nil."
              (if (looking-at "[({[]\\s-*\\(/[/*]\\|$\\)")
                  (progn
                    (skip-syntax-backward " ")
-                   (when (= (char-before) ?\)) (backward-list))
+                  (when (eq (char-before) ?\)) (backward-list))
                    (back-to-indentation)
                    (cond (same-indent-p
                           (current-column))
@@ -1827,8 +1851,8 @@ nil."
 (defun js--make-merged-item (item child name-parts)
   "Helper function for `js--splice-into-items'.
 Return a new item that is the result of merging CHILD into
-ITEM. NAME-PARTS is a list of parts of the name of CHILD that we
-haven't consumed yet."
+ITEM.  NAME-PARTS is a list of parts of the name of CHILD
+that we haven't consumed yet."
   (js--debug "js--make-merged-item: {%s} into {%s}"
                    (js--pitem-format child)
                    (js--pitem-format item))
@@ -1878,9 +1902,9 @@ haven't consumed yet."
 
 (defun js--splice-into-items (items child name-parts)
   "Splice CHILD into the `js--pitem' ITEMS at NAME-PARTS.
-If a class doesn't exist in the tree, create it. Return the new
-items list.  NAME-PARTS is a list of strings given the
-broken-down class name of the item to insert."
+If a class doesn't exist in the tree, create it.  Return
+the new items list.  NAME-PARTS is a list of strings given
+the broken-down class name of the item to insert."
 
   (let ((top-name (car name-parts))
         (item-ptr items)
@@ -2086,7 +2110,7 @@ broken-down class name of the item to insert."
              (puthash name2 (cdr item) symbols))))
 
 (defun js--get-all-known-symbols ()
-  "Return a hash table of all Javascript symbols.
+  "Return a hash table of all JavaScript symbols.
 This searches all existing `js-mode' buffers. Each key is the
 name of a symbol (possibly disambiguated with <N>, where N > 1),
 and each value is a marker giving the location of that symbol."
@@ -2100,7 +2124,7 @@ and each value is a marker giving the location of that symbol."
         finally return symbols))
 
 (defvar js--symbol-history nil
-  "History of entered Javascript symbols")
+  "History of entered JavaScript symbols.")
 
 (defun js--read-symbol (symbols-table prompt &optional initial-input)
   "Helper function for `js-find-symbol'.
@@ -2131,9 +2155,9 @@ marker."
       (buffer-substring (car bounds) (cdr bounds)))))
 
 (defun js-find-symbol (&optional arg)
-  "Read a Javascript symbol and jump to it.
+  "Read a JavaScript symbol and jump to it.
 With a prefix argument, restrict symbols to those from the
-current buffer. Pushes a mark onto the tag ring just like
+current buffer.  Pushes a mark onto the tag ring just like
 `find-tag'."
   (interactive "P")
   (let (symbols marker)
@@ -2192,7 +2216,7 @@ Otherwise, use the current value of `process-mark'."
            (inferior-moz-process))))
 
 (defvar js--js-references nil
-  "Maps Elisp Javascript proxy objects to their Javascript IDs.")
+  "Maps Elisp JavaScript proxy objects to their JavaScript IDs.")
 
 (defvar js--js-process nil
   "The most recent MozRepl process object.")
@@ -2512,12 +2536,12 @@ Otherwise, use the current value of `process-mark'."
 })
 ")
 
-  "String to set MozRepl up into a simple-minded evaluation mode")
+  "String to set MozRepl up into a simple-minded evaluation mode.")
 
 (defun js--js-encode-value (x)
   "Marshall the given value for JS.
 Strings and numbers are JSON-encoded.  Lists (including nil) are
-made into Javascript array literals and their contents encoded
+made into JavaScript array literals and their contents encoded
 with `js--js-encode-value'."
   (cond ((stringp x) (json-encode-string x))
         ((numberp x) (json-encode-number x))
@@ -2604,7 +2628,7 @@ with `js--js-encode-value'."
        js-js-timeout))))
 
 (defsubst js--js-not (value)
-  (memq value '(nil false undefined)))
+  (memq value '(nil null false undefined)))
 
 (defsubst js--js-true (value)
   (not (js--js-not value)))
@@ -2822,7 +2846,7 @@ With argument, run even if no intervening GC has happened."
       (setq num (js--js-funcall '(repl "_jsGC") (or keys [])))
 
       (setq js--js-last-gcs-done this-gcs-done)
-      (when (interactive-p)
+      (when (called-interactively-p 'interactive)
         (message "Cleaned %s entries" num))
 
       num)))
@@ -2836,7 +2860,7 @@ With argument, run even if no intervening GC has happened."
    (let* ((content-window (js--js-content-window
                            (js--get-js-context)))
           (result (js-eval content-window js)))
-     (when (interactive-p)
+     (when (called-interactively-p 'interactive)
        (message "%s" (js! "String" result)))
      result)))
 
@@ -2910,7 +2934,7 @@ left-to-right."
 (defun js--read-tab (prompt)
   "Read a Mozilla tab with prompt PROMPT.
 Return a cons of (TYPE . OBJECT).  TYPE is either 'window or
-'tab, and OBJECT is a Javascript handle to a ChromeWindow or a
+'tab, and OBJECT is a JavaScript handle to a ChromeWindow or a
 browser, respectively."
 
   ;; Prime IDO
@@ -3303,6 +3327,13 @@ Key bindings:
         comment-start-skip "\\(//+\\|/\\*+\\)\\s *")
 
   (let ((c-buffer-is-cc-mode t))
+    ;; FIXME: These are normally set by `c-basic-common-init'.  Should
+    ;; we call it instead?  (Bug#6071)
+    (make-local-variable 'paragraph-start)
+    (make-local-variable 'paragraph-separate)
+    (make-local-variable 'paragraph-ignore-fill-prefix)
+    (make-local-variable 'adaptive-fill-mode)
+    (make-local-variable 'adaptive-fill-regexp)
     (c-setup-paragraph-variables))
 
   (set (make-local-variable 'syntax-begin-function)
@@ -3321,6 +3352,7 @@ Key bindings:
   (let (font-lock-keywords) ; leaves syntactic keywords intact
     (font-lock-fontify-buffer)))
 
+;;;###autoload
 (defalias 'javascript-mode 'js-mode)
 
 (eval-after-load 'folding