[bknr-cvs] r2291 - branches/trunk-reorg/thirdparty/emacs

bknr at bknr.net bknr at bknr.net
Tue Nov 27 11:01:52 UTC 2007


Author: hhubner
Date: 2007-11-27 06:01:50 -0500 (Tue, 27 Nov 2007)
New Revision: 2291

Added:
   branches/trunk-reorg/thirdparty/emacs/javascript.el
   branches/trunk-reorg/thirdparty/emacs/js-mode.el
   branches/trunk-reorg/thirdparty/emacs/shellserver.xpi
Log:
Add Javascript development aids.


Added: branches/trunk-reorg/thirdparty/emacs/javascript.el
===================================================================
--- branches/trunk-reorg/thirdparty/emacs/javascript.el	2007-11-26 12:43:25 UTC (rev 2290)
+++ branches/trunk-reorg/thirdparty/emacs/javascript.el	2007-11-27 11:01:50 UTC (rev 2291)
@@ -0,0 +1,736 @@
+;;; javascript.el --- Major mode for editing JavaScript source text
+
+;; Copyright (C) 2006 Karl Landström
+
+;; Author: Karl Landström <kland at comhem.se>
+;; Maintainer: Karl Landström <kland at comhem.se>
+;; Version: 2.0 Beta 8
+;; Date: 2006-12-26
+;; Keywords: languages, oop
+
+;; This version contains a few font-lock fixes for quoted strings
+;; and regular expressions by Joost Diepenmaat <joost at zeekat.nl>
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING.  If not, write to
+;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;;
+;; The main features of this JavaScript mode are syntactic
+;; highlighting (enabled with `font-lock-mode' or
+;; `global-font-lock-mode'), automatic indentation and filling of
+;; comments.
+;;
+;; This package has (only) been tested with GNU Emacs 21.4 (the latest
+;; stable release).
+;;
+;; Installation:
+;;
+;; Put this file in a directory where Emacs can find it (`C-h v
+;; load-path' for more info). Then add the following lines to your
+;; Emacs initialization file:
+;; 
+;;    (add-to-list 'auto-mode-alist '("\\.js\\'" . javascript-mode))
+;;    (autoload 'javascript-mode "javascript" nil t)
+;;    
+;; General Remarks:
+;; 
+;; This mode assumes that block comments are not nested inside block
+;; comments and that strings do not contain line breaks.
+;; 
+;; Exported names start with "javascript-" whereas private names start
+;; with "js-".
+;; 
+;; Changes:
+;;
+;; See javascript.el.changelog.
+
+;;; Code:
+
+(require 'cc-mode)
+(require 'font-lock)
+(require 'newcomment)
+
+(defgroup javascript nil 
+  "Customization variables for `javascript-mode'."
+  :tag "JavaScript"
+  :group 'languages)
+
+(defcustom javascript-indent-level 4
+  "Number of spaces for each indentation step."
+  :type 'integer
+  :group 'javascript)
+
+(defcustom javascript-auto-indent-flag t
+  "Automatic indentation with punctuation characters. If non-nil, the
+current line is indented when certain punctuations are inserted."
+  :type 'boolean
+  :group 'javascript)
+
+
+;; --- Keymap ---
+
+(defvar javascript-mode-map nil 
+  "Keymap used in JavaScript mode.")
+
+(unless javascript-mode-map 
+  (setq javascript-mode-map (make-sparse-keymap)))
+
+(when javascript-auto-indent-flag
+  (mapc (lambda (key) 
+	  (define-key javascript-mode-map key 'javascript-insert-and-indent))
+	'("{" "}" "(" ")" ":" ";" ",")))
+
+(defun javascript-insert-and-indent (key)
+  "Run command bound to key and indent current line. Runs the command
+bound to KEY in the global keymap and indents the current line."
+  (interactive (list (this-command-keys)))
+  (call-interactively (lookup-key (current-global-map) key))
+  (indent-according-to-mode))
+
+
+;; --- Syntax Table And Parsing ---
+
+(defvar javascript-mode-syntax-table
+  (let ((table (make-syntax-table)))
+    (c-populate-syntax-table table)
+
+    ;; switch off build-in quoted string detection
+    ;; since that just makes it really hard to detect
+    ;; regular expressions and comments
+    ;;
+    ;; this also has the benefit that multiline strings
+    ;; are now not recognized as strings (since javascript does
+    ;; not allow them)
+    (modify-syntax-entry ?' "." table)
+    (modify-syntax-entry ?\" "." table)
+
+    ;; The syntax class of underscore should really be `symbol' ("_")
+    ;; but that makes matching of tokens much more complex as e.g.
+    ;; "\\<xyz\\>" matches part of e.g. "_xyz" and "xyz_abc". Defines
+    ;; it as word constituent for now.
+    (modify-syntax-entry ?_ "w" table)
+
+    table)
+  "Syntax table used in JavaScript mode.")
+
+
+(defun js-re-search-forward-inner (regexp &optional bound count)
+  "Auxiliary function for `js-re-search-forward'."
+  (let ((parse)
+        (saved-point (point-min)))
+    (while (> count 0)
+      (re-search-forward regexp bound)
+      (setq parse (parse-partial-sexp saved-point (point)))
+      (cond ((nth 3 parse)
+             (re-search-forward 
+              (concat "\\([^\\]\\|^\\)" (string (nth 3 parse))) 
+              (save-excursion (end-of-line) (point)) t))
+            ((nth 7 parse)
+             (forward-line))
+            ((or (nth 4 parse)
+                 (and (eq (char-before) ?\/) (eq (char-after) ?\*)))
+             (re-search-forward "\\*/"))
+            (t
+             (setq count (1- count))))
+      (setq saved-point (point))))
+  (point))
+
+
+(defun js-re-search-forward (regexp &optional bound noerror count)
+  "Search forward but ignore strings and comments. Invokes
+`re-search-forward' but treats the buffer as if strings and
+comments have been removed."
+  (let ((saved-point (point))
+        (search-expr 
+         (cond ((null count)
+                '(js-re-search-forward-inner regexp bound 1))
+               ((< count 0)
+                '(js-re-search-backward-inner regexp bound (- count)))
+               ((> count 0)
+                '(js-re-search-forward-inner regexp bound count)))))
+    (condition-case err
+        (eval search-expr)
+      (search-failed
+       (goto-char saved-point)
+       (unless noerror
+         (error (error-message-string err)))))))
+
+
+(defun js-re-search-backward-inner (regexp &optional bound count)
+  "Auxiliary function for `js-re-search-backward'."
+  (let ((parse)
+        (saved-point (point-min)))
+    (while (> count 0)
+      (re-search-backward regexp bound)
+      (when (and (> (point) (point-min))
+                 (save-excursion (backward-char) (looking-at "/[/*]")))
+        (forward-char))
+      (setq parse (parse-partial-sexp saved-point (point)))
+      (cond ((nth 3 parse)
+             (re-search-backward
+              (concat "\\([^\\]\\|^\\)" (string (nth 3 parse))) 
+              (save-excursion (beginning-of-line) (point)) t))
+            ((nth 7 parse) 
+             (goto-char (nth 8 parse)))
+            ((or (nth 4 parse)
+                 (and (eq (char-before) ?/) (eq (char-after) ?*)))
+             (re-search-backward "/\\*"))
+            (t
+             (setq count (1- count))))))
+  (point))
+
+
+(defun js-re-search-backward (regexp &optional bound noerror count)
+  "Search backward but ignore strings and comments. Invokes
+`re-search-backward' but treats the buffer as if strings and
+comments have been removed."
+  (let ((saved-point (point))
+        (search-expr 
+         (cond ((null count)
+                '(js-re-search-backward-inner regexp bound 1))
+               ((< count 0)
+                '(js-re-search-forward-inner regexp bound (- count)))
+               ((> count 0)
+                '(js-re-search-backward-inner regexp bound count)))))
+    (condition-case err
+        (eval search-expr)
+      (search-failed
+       (goto-char saved-point)
+       (unless noerror
+         (error (error-message-string err)))))))
+
+
+(defun js-continued-var-decl-list-p ()
+  "Return non-nil if point is inside a continued variable declaration
+list."
+  (interactive)
+  (let ((start (save-excursion (js-re-search-backward "\\<var\\>" nil t))))
+    (and start
+	 (save-excursion (re-search-backward "\n" start t))
+	 (not (save-excursion 
+		(js-re-search-backward 
+		 ";\\|[^, \t][ \t]*\\(/[/*]\\|$\\)" start t))))))
+
+
+;; --- Font Lock ---
+
+(defun js-inside-param-list-p ()
+  "Return non-nil if point is inside a function parameter list."
+  (condition-case err
+      (save-excursion
+	(up-list -1)
+	(and (looking-at "(")
+	     (progn (backward-word 1)
+		    (or (looking-at "function")
+			(progn (backward-word 1) (looking-at "function"))))))
+    (error nil)))
+
+
+(defconst js-function-heading-1-re 
+  "^[ \t]*function[ \t]+\\(\\w+\\)"
+  "Regular expression matching the start of a function header.")
+
+(defconst js-function-heading-2-re 
+  "^[ \t]*\\(\\w+\\)[ \t]*:[ \t]*function\\>"
+  "Regular expression matching the start of a function entry in
+  an associative array.")
+
+(defconst js-keyword-re
+  (regexp-opt '("abstract" "break" "case" "catch" "class" "const"
+                "continue" "debugger" "default" "delete" "do" "else" 
+                "enum" "export" "extends" "final" "finally" "for" 
+                "function" "goto" "if" "implements" "import" "in" 
+                "instanceof" "interface" "native" "new" "package" 
+                "private" "protected" "public" "return" "static" 
+                "super" "switch" "synchronized" "this" "throw" 
+                "throws" "transient" "try" "typeof" "var" "void" 
+                "volatile" "while" "with") 'words)
+  "Regular expression matching any JavaScript keyword.")
+
+(defconst js-basic-type-re
+  (regexp-opt '("boolean" "byte" "char" "double" "float" "int" "long"
+                "short" "void") 'words)
+  "Regular expression matching any predefined type in JavaScript.")
+
+(defconst js-constant-re
+  (regexp-opt '("false" "null" "true") 'words)
+  "Regular expression matching any future reserved words in JavaScript.")
+
+
+(defconst js-quoted-string-re "\\(\".*?[^\\]\"\\|'.*?[^\\]'\\)")
+(defconst js-quoted-string-or-regex-re "\\(/.*?[^\\]/\\w*\\|\".*?[^\\]\"\\|'.*?[^\\]'\\)")
+
+
+(defconst js-font-lock-keywords-1
+  (list 
+   "\\<import\\>" 
+   (list js-function-heading-1-re 1 font-lock-function-name-face)
+   (list js-function-heading-2-re 1 font-lock-function-name-face)
+
+   ;; detect literal strings following a + operator
+   (list (concat "+[ \t]*" js-quoted-string-re)  1 font-lock-string-face)
+
+   ;; detect literal strings used in "literal object" keys
+   (list (concat "[,{][ \t]*" js-quoted-string-re "[ \t]*:" ) 1 font-lock-string-face)
+
+   ;; detects strings and regexes when assigned, passed, returned
+   ;; used as an object key string (i.e. bla["some string"]), when used
+   ;; as a literal object value (i.e. key: "string"), used as an array
+   ;; element, or when they appear as the first expression on a line
+   ;; and a few other hairy cases
+   (list (concat "[=(:,;[][ \t]*" js-quoted-string-or-regex-re)  1 font-lock-string-face)
+   (list (concat "^[ \t]*"      js-quoted-string-or-regex-re) 1 font-lock-string-face)
+   (list (concat "return[ \t]*" js-quoted-string-or-regex-re) 1 font-lock-string-face)
+
+   ;; detect "autoquoted" object properties... clases with "switch { ...  default: }"
+   ;; may not be worth the trouble
+   (list "\\(^[ \t]*\\|[,{][ \t]*\\)\\(\\w+\\):" 2 font-lock-string-face))
+
+  "Level one font lock.")
+
+(defconst js-font-lock-keywords-2
+  (append js-font-lock-keywords-1
+          (list (list js-keyword-re 1 font-lock-keyword-face)
+                (cons js-basic-type-re font-lock-type-face)
+                (cons js-constant-re font-lock-constant-face)))
+  "Level two font lock.")
+
+
+;; Limitations with variable declarations: There seems to be no
+;; sensible way to highlight variables occuring after an initialized
+;; variable in a variable list. For instance, in
+;;
+;;    var x, y = f(a, b), z
+;;
+;; z will not be highlighted.
+
+(defconst js-font-lock-keywords-3
+  (append 
+   js-font-lock-keywords-2
+   (list 
+
+    ;; variable declarations
+    (list
+     (concat "\\<\\(const\\|var\\)\\>\\|" js-basic-type-re)
+     (list "\\(\\w+\\)[ \t]*\\([=;].*\\|,\\|/[/*]\\|$\\)"
+	   nil
+	   nil
+	   '(1 font-lock-variable-name-face)))
+
+    ;; continued variable declaration list
+    (list
+     (concat "^[ \t]*\\w+[ \t]*\\([,;=]\\|/[/*]\\|$\\)")
+     (list "\\(\\w+\\)[ \t]*\\([=;].*\\|,\\|/[/*]\\|$\\)"
+	   '(if (save-excursion (backward-char) (js-continued-var-decl-list-p))
+		(backward-word 1) 
+	      (end-of-line))
+	   '(end-of-line)
+	   '(1 font-lock-variable-name-face)))
+
+    ;; formal parameters
+    (list
+     (concat "\\<function\\>\\([ \t]+\\w+\\)?[ \t]*([ \t]*\\w")
+     (list "\\(\\w+\\)\\([ \t]*).*\\)?"
+	   '(backward-char)
+	   '(end-of-line)
+	   '(1 font-lock-variable-name-face)))
+    
+    ;; continued formal parameter list
+    (list
+     (concat "^[ \t]*\\w+[ \t]*[,)]")
+     (list "\\w+"
+	   '(if (save-excursion (backward-char) (js-inside-param-list-p))
+		(backward-word 1) 
+	      (end-of-line))
+	   '(end-of-line)
+	   '(0 font-lock-variable-name-face)))))
+  "Level three font lock.")
+
+(defconst js-font-lock-keywords
+  '(js-font-lock-keywords-3 js-font-lock-keywords-1 js-font-lock-keywords-2
+                            js-font-lock-keywords-3)
+  "See `font-lock-keywords'.")
+
+
+;; --- Indentation ---
+
+(defconst js-possibly-braceless-keyword-re
+  (regexp-opt
+   '("catch" "do" "else" "finally" "for" "if" "try" "while" "with")
+   'words)
+  "Regular expression matching keywords that are optionally
+  followed by an opening brace.")
+
+(defconst js-indent-operator-re
+  (concat "[-+*/%<>=&^|?:]\\([^-+*/]\\|$\\)\\|"
+          (regexp-opt '("in" "instanceof") 'words))
+  "Regular expression matching operators that affect indentation
+  of continued expressions.")
+
+
+(defun js-looking-at-operator-p ()
+  "Return non-nil if text after point is an operator (that is not
+a comma)."
+  (save-match-data
+    (and (looking-at js-indent-operator-re)
+         (or (not (looking-at ":"))
+             (save-excursion
+               (and (js-re-search-backward "[?:{]\\|\\<case\\>" nil t)
+                    (looking-at "?")))))))
+
+
+(defun js-continued-expression-p ()
+  "Returns non-nil if the current line continues an expression."
+  (save-excursion
+    (back-to-indentation)
+    (or (js-looking-at-operator-p)
+        (and (js-re-search-backward "\n" nil t)
+	     (progn 
+	       (skip-chars-backward " \t")
+	       (backward-char)
+	       (and (> (point) (point-min))
+                    (save-excursion (backward-char) (not (looking-at "[/*]/")))
+                    (js-looking-at-operator-p)
+		    (and (progn (backward-char)
+				(not (looking-at "++\\|--\\|/[/*]"))))))))))
+
+
+(defun js-end-of-do-while-loop-p ()
+  "Returns non-nil if word after point is `while' of a do-while
+statement, else returns nil. A braceless do-while statement
+spanning several lines requires that the start of the loop is
+indented to the same column as the current line."
+  (interactive)
+  (save-excursion
+    (save-match-data
+      (when (looking-at "\\s-*\\<while\\>")
+	(if (save-excursion 
+	      (skip-chars-backward "[ \t\n]*}")
+	      (looking-at "[ \t\n]*}"))
+	    (save-excursion 
+	      (backward-list) (backward-word 1) (looking-at "\\<do\\>"))
+	  (js-re-search-backward "\\<do\\>" (point-at-bol) t)
+	  (or (looking-at "\\<do\\>")
+	      (let ((saved-indent (current-indentation)))
+		(while (and (js-re-search-backward "^[ \t]*\\<" nil t)
+			    (/= (current-indentation) saved-indent)))
+		(and (looking-at "[ \t]*\\<do\\>")
+		     (not (js-re-search-forward 
+			   "\\<while\\>" (point-at-eol) t))
+		     (= (current-indentation) saved-indent)))))))))
+
+
+(defun js-ctrl-statement-indentation ()
+  "Returns the proper indentation of the current line if it
+starts the body of a control statement without braces, else
+returns nil."
+  (save-excursion
+    (back-to-indentation)
+    (when (save-excursion
+            (and (not (looking-at "[{]"))
+                 (progn
+                   (js-re-search-backward "[[:graph:]]" nil t)
+                   (forward-char)
+                   (when (= (char-before) ?\)) (backward-list))
+                   (skip-syntax-backward " ")
+                   (skip-syntax-backward "w")
+                   (looking-at js-possibly-braceless-keyword-re))
+                 (not (js-end-of-do-while-loop-p))))
+      (save-excursion
+        (goto-char (match-beginning 0))
+        (+ (current-indentation) javascript-indent-level)))))
+
+
+(defun js-proper-indentation (parse-status)
+  "Return the proper indentation for the current line."
+  (save-excursion
+    (back-to-indentation)
+    (let ((ctrl-stmt-indent (js-ctrl-statement-indentation))
+          (same-indent-p (looking-at "[]})]\\|\\<case\\>\\|\\<default\\>"))
+          (continued-expr-p (js-continued-expression-p)))
+      (cond (ctrl-stmt-indent)
+	    ((js-continued-var-decl-list-p)
+	     (js-re-search-backward "\\<var\\>" nil t)
+	     (+ (current-indentation) javascript-indent-level))
+            ((nth 1 parse-status)
+             (goto-char (nth 1 parse-status))
+             (if (looking-at "[({[][ \t]*\\(/[/*]\\|$\\)")
+                 (progn
+                   (skip-syntax-backward " ")
+                   (when (= (char-before) ?\)) (backward-list))
+                   (back-to-indentation)
+                   (cond (same-indent-p
+                          (current-column))
+                         (continued-expr-p
+                          (+ (current-column) (* 2 javascript-indent-level)))
+                         (t
+                          (+ (current-column) javascript-indent-level))))
+               (unless same-indent-p
+                 (forward-char)
+                 (skip-chars-forward " \t"))
+               (current-column)))
+	    (continued-expr-p javascript-indent-level)
+            (t 0)))))
+
+
+(defun javascript-indent-line ()
+  "Indent the current line as JavaScript source text."
+  (interactive)
+  (let ((parse-status 
+         (save-excursion (parse-partial-sexp (point-min) (point-at-bol))))
+        (offset (- (current-column) (current-indentation))))
+    (when (not (nth 8 parse-status))
+      (indent-line-to (js-proper-indentation parse-status))
+      (when (> offset 0) (forward-char offset)))))
+
+
+;; --- Filling ---
+
+;; FIXME: It should be possible to use the more sofisticated function
+;; `c-fill-paragraph' in `cc-cmds.el' instead. However, just setting
+;; `fill-paragraph-function' to `c-fill-paragraph' does not work;
+;; inside `c-fill-paragraph', `fill-paragraph-function' evaluates to
+;; nil!?
+
+(defun js-backward-paragraph ()
+  "Move backward to start of paragraph. Postcondition: Point is at
+beginning of buffer or the previous line contains only whitespace."
+  (forward-line -1)
+  (while (not (or (bobp) (looking-at "^[ \t]*$")))
+    (forward-line -1))
+  (when (not (bobp)) (forward-line 1)))
+
+
+(defun js-forward-paragraph ()
+  "Move forward to end of paragraph. Postcondition: Point is at
+end of buffer or the next line contains only whitespace."
+  (forward-line 1)
+  (while (not (or (eobp) (looking-at "^[ \t]*$")))
+    (forward-line 1))
+  (when (not (eobp)) (backward-char 1)))
+ 
+
+(defun js-fill-block-comment-paragraph (parse-status justify)
+  "Fill current paragraph as a block comment. PARSE-STATUS is the
+result of `parse-partial-regexp' from beginning of buffer to
+point. JUSTIFY has the same meaning as in `fill-paragraph'."
+  (let ((offset (save-excursion 
+                  (goto-char (nth 8 parse-status)) (current-indentation))))
+    (save-excursion
+      (save-restriction
+        (narrow-to-region (save-excursion 
+                            (goto-char (nth 8 parse-status)) (point-at-bol))
+                          (save-excursion 
+			    (goto-char (nth 8 parse-status))
+			    (re-search-forward "*/")))
+        (narrow-to-region (save-excursion 
+                            (js-backward-paragraph)
+                            (when (looking-at "^[ \t]*$") (forward-line 1))
+                            (point))
+                          (save-excursion 
+                            (js-forward-paragraph) 
+                            (when (looking-at "^[ \t]*$") (backward-char))
+                            (point)))
+        (goto-char (point-min))
+        (while (not (eobp))
+          (delete-horizontal-space)
+          (forward-line 1))
+        (let ((fill-column (- fill-column offset))
+              (fill-paragraph-function nil))
+          (fill-paragraph justify))
+
+        ;; In Emacs 21.4 as opposed to CVS Emacs 22,
+        ;; `fill-paragraph' seems toadd a newline at the end of the
+        ;; paragraph. Remove it!
+        (goto-char (point-max))
+        (when (looking-at "^$") (backward-delete-char 1))
+
+        (goto-char (point-min))
+        (while (not (eobp))
+          (indent-to offset)
+          (forward-line 1))))))
+
+
+(defun js-sline-comment-par-start ()
+  "Return point at the beginning of the line where the current
+single-line comment paragraph starts."
+  (save-excursion
+    (beginning-of-line)
+    (while (and (not (bobp)) 
+                (looking-at "^[ \t]*//[ \t]*[[:graph:]]"))
+      (forward-line -1))
+    (unless (bobp) (forward-line 1))
+    (point)))
+
+
+(defun js-sline-comment-par-end ()
+  "Return point at end of current single-line comment paragraph."
+  (save-excursion
+    (beginning-of-line)
+    (while (and (not (eobp)) 
+                (looking-at "^[ \t]*//[ \t]*[[:graph:]]"))
+      (forward-line 1))
+    (unless (bobp) (backward-char))
+    (point)))
+
+
+(defun js-sline-comment-offset (line)
+  "Return the column at the start of the current single-line
+comment paragraph."
+  (save-excursion 
+    (goto-line line)
+    (re-search-forward "//" (point-at-eol))
+    (goto-char (match-beginning 0))
+    (current-column)))
+
+
+(defun js-sline-comment-text-offset (line)
+  "Return the column at the start of the text of the current
+single-line comment paragraph."
+  (save-excursion
+    (goto-line line)
+    (re-search-forward "//[ \t]*" (point-at-eol))
+    (current-column)))
+
+
+(defun js-at-empty-sline-comment-p ()
+  "Return non-nil if inside an empty single-line comment."
+  (and (save-excursion
+         (beginning-of-line)
+         (not (looking-at "^.*//.*[[:graph:]]")))
+       (save-excursion
+         (re-search-backward "//" (point-at-bol) t))))
+
+         
+(defun js-fill-sline-comments (parse-status justify)
+  "Fill current paragraph as a sequence of single-line comments.
+PARSE-STATUS is the result of `parse-partial-regexp' from
+beginning of buffer to point. JUSTIFY has the same meaning as in
+`fill-paragraph'."
+  (when (not (js-at-empty-sline-comment-p))
+    (let* ((start (js-sline-comment-par-start))
+           (start-line (1+ (count-lines (point-min) start)))
+           (end (js-sline-comment-par-end))
+           (offset (js-sline-comment-offset start-line))
+           (text-offset (js-sline-comment-text-offset start-line)))
+      (save-excursion
+        (save-restriction
+          (narrow-to-region start end)
+          (goto-char (point-min))
+          (while (re-search-forward "^[ \t]*//[ \t]*" nil t)
+            (replace-match "")
+            (forward-line 1))
+          (let ((fill-paragraph-function nil)
+                (fill-column (- fill-column text-offset)))
+            (fill-paragraph justify))
+
+          ;; In Emacs 21.4 as opposed to CVS Emacs 22,
+          ;; `fill-paragraph' seems toadd a newline at the end of the
+          ;; paragraph. Remove it!
+          (goto-char (point-max))
+          (when (looking-at "^$") (backward-delete-char 1))
+
+          (goto-char (point-min))
+          (while (not (eobp))
+            (indent-to offset)
+            (insert "//")
+            (indent-to text-offset)
+            (forward-line 1)))))))
+  
+
+(defun js-trailing-comment-p (parse-status)
+  "Return non-nil if inside a trailing comment. PARSE-STATUS is
+the result of `parse-partial-regexp' from beginning of buffer to
+point."
+  (save-excursion 
+    (when (nth 4 parse-status)
+      (goto-char (nth 8 parse-status))
+      (skip-chars-backward " \t")
+      (not (bolp)))))
+
+
+(defun js-block-comment-p (parse-status)
+  "Return non-nil if inside a block comment. PARSE-STATUS is the
+result of `parse-partial-regexp' from beginning of buffer to
+point."
+  (save-excursion 
+    (save-match-data
+      (when (nth 4 parse-status)
+        (goto-char (nth 8 parse-status))
+        (looking-at "/\\*")))))
+
+
+(defun javascript-fill-paragraph (&optional justify)
+  "If inside a comment, fill the current comment paragraph.
+Trailing comments are ignored."
+  (interactive)
+  (let ((parse-status (parse-partial-sexp (point-min) (point))))
+    (when (and (nth 4 parse-status) 
+               (not (js-trailing-comment-p parse-status)))
+      (if (js-block-comment-p parse-status)
+          (js-fill-block-comment-paragraph parse-status justify)
+        (js-fill-sline-comments parse-status justify))))
+  t)
+
+
+;; --- Imenu ---
+
+(defconst js-imenu-generic-expression 
+  (list
+   (list
+    nil 
+    "function\\s-+\\(\\w+\\)\\s-*("
+    1))
+  "Regular expression matching top level procedures. Used by imenu.")
+
+
+;; --- Main Function ---
+
+;;;###autoload
+(defun javascript-mode ()
+  "Major mode for editing JavaScript source text.
+
+Key bindings:
+
+\\{javascript-mode-map}"
+  (interactive)
+  (kill-all-local-variables)
+
+  (use-local-map javascript-mode-map)
+  (set-syntax-table javascript-mode-syntax-table)
+  (set (make-local-variable 'indent-line-function) 'javascript-indent-line)
+  (set (make-local-variable 'font-lock-defaults) (list js-font-lock-keywords))
+
+  (set (make-local-variable 'parse-sexp-ignore-comments) t) 
+
+  ;; Comments
+  (setq comment-start "// ")
+  (setq comment-end "")
+  (set (make-local-variable 'fill-paragraph-function) 
+       'javascript-fill-paragraph)
+
+  ;; Imenu
+  (setq imenu-case-fold-search nil)
+  (set (make-local-variable 'imenu-generic-expression)
+       js-imenu-generic-expression)
+
+  (setq major-mode 'javascript-mode)
+  (setq mode-name "JavaScript")
+  (run-hooks 'javascript-mode-hook))
+
+
+(provide 'javascript-mode)
+;;; javascript.el ends here

Added: branches/trunk-reorg/thirdparty/emacs/js-mode.el
===================================================================
--- branches/trunk-reorg/thirdparty/emacs/js-mode.el	2007-11-26 12:43:25 UTC (rev 2290)
+++ branches/trunk-reorg/thirdparty/emacs/js-mode.el	2007-11-27 11:01:50 UTC (rev 2291)
@@ -0,0 +1,759 @@
+;;; js-mode.el --- minor mode for interacting with Mozilla
+;;
+;; Copyright (C) 2004  Helmut Eller
+;;
+;; You can redistribute this file under the terms of the GNU General
+;; Public License.
+;;
+
+;;; Commentary:
+;;
+;; This file implements some commands for interacting with Mozilla
+;; from Emacs.  Emacs uses a TCP connection to communicate with
+;; Mozilla.  The available commands are:
+;;   
+;;    C-c :     Sends a piece of Javascript code to Mozilla for evaluation
+;;              and prints the result.  
+;;  	        
+;;    C-M-x     Evaluates the current function defintion in Mozilla.
+;;    C-c C-e   Evaluates the current line.
+;;    C-c C-r   Evaluates the current region
+;;   	        
+;;    C-c C-l   Loads a javascript file.
+;;	        
+;;    M-.       Finds the source location of function definitions.
+;;    M-,       Returns to the origin of the last M-. command.
+;;
+;;    C-c C-d   Can be used to inspect the Javascript objects.
+;;
+;; This file also implements a simple debugger.  The debugger is
+;; invoked when an error occurs.  The debugger can show the backtrace,
+;; the values of local variables in frames and the source location
+;; corresponding to frames.  It is also possible to invoke the
+;; debugger exlicitly by inserting the "debugger" keyword in javacript
+;; code.  Furthermore, the debugger can be invoked on throw
+;; statements.  Use C-c C-b t to enable debugging on throw.
+;; 
+;; Installation:
+;; 
+;; - First you have to load the server in Mozilla.  You can add the
+;; file emacsslave.js to your rc file or make the neccessary
+;; modifications to conkeror itself.  The server can be started with
+;; M-x start-server in Conkeror.
+;;
+;; - Put this file into your Emacs load path add something like this
+;; to your .emacs:
+;;    
+;;    (add-hook 'javascript-mode-hook 'js-mode)
+;;    (autoload 'js-mode "js-mode" nil t)
+;;      
+;; - Then open a javascript file and make sure js-mode is enabled.  To
+;; connect to Mozilla type M-x js-connect.
+;;
+;; - Then you can try the commands from above.
+;;
+;;; 
+;;
+;; The code should work in Emacs 20.7 and Emacs 21.  XEmacs
+;; compatibility is a bit problematic at the moment.
+
+;;; Code:
+
+(eval-and-compile
+  (require 'cl)
+  (unless (fboundp 'define-minor-mode)
+    (require 'easy-mmode)
+    (defalias 'define-minor-mode 'easy-mmode-define-minor-mode)))
+
+(require 'pp)
+(require 'cc-mode)
+
+(defvar js-mode-map (make-sparse-keymap))
+
+(define-minor-mode js-mode 
+  "Minor mode for interacting with Mozilla.
+
+Use \\[js-connect] to establish a connection with Mozilla.
+Some other commands are:
+\\{js-mode-map}"
+  nil nil ())
+
+(add-to-list 'minor-mode-alist 
+	     '(js-mode (js-mozilla-connection " [js]" " js")))
+
+(define-key js-mode-map (kbd "M-C-x") 'js-eval-defun)
+(define-key js-mode-map (kbd "C-c :") 'js-interactive-eval)
+(define-key js-mode-map (kbd "C-c C-e") 'js-eval-current-line)
+(define-key js-mode-map (kbd "C-c C-r") 'js-eval-region)
+(define-key js-mode-map (kbd "C-c C-l") 'js-load-file)
+(define-key js-mode-map (kbd "M-.") 'js-find-definitions)
+(define-key js-mode-map (kbd "M-,") 'js-pop-find-definition-stack)
+(define-key js-mode-map (kbd "C-c C-d")   'js-inspect)
+(define-key js-mode-map (kbd "C-c C-b t")   'js-toggle-break-on-throw)
+(define-key js-mode-map (kbd "C-c C-b C-t") 'js-toggle-break-on-throw)
+
+
+;;; Generally useful stuff
+
+(defun js-symbol-at-point ()
+  "Return the symbol at point as string, or nil."
+  (save-restriction
+    (save-excursion
+      (let ((string (thing-at-point 'symbol)))
+        (and string (not (equal string ""))
+             (substring-no-properties string))))))
+
+(defun js-read-symbol (prompt &optional query)
+  "Either read a symbol name or choose the one at point.
+The user is prompted if a prefix argument is in effect, if there is no
+symbol at point, or if QUERY is non-nil."
+  (cond ((or current-prefix-arg query (not (js-symbol-at-point)))
+         (read-from-minibuffer prompt (js-symbol-at-point)))
+        (t (js-symbol-at-point))))
+
+(make-variable-buffer-local
+ (defvar js-old-window-config nil
+   "The window configuration before when before temp-buffer was displayed.
+Buffer local in temp-buffers."))
+
+
+
+;;; Networking
+
+(defvar js-mozilla-connection nil)
+
+(defun js-connect (port)
+  "Connect to Mozilla on PORT."
+  (interactive (list (read-from-minibuffer "Port: " "4007" nil t)))
+  (let ((socket (js-net-connect port)))
+    (setq js-mozilla-connection socket)
+    (js-eval `(mozilla_info) (lambda (info) 
+			       (message "Connected to: %s" (car info))))))
+
+(defun js-disconnect ()
+  "Close the connection to Mozilla."
+  (interactive)
+  (delete-process js-mozilla-connection)
+  (setq js-mozilla-connection nil))
+
+(defun js-connection ()
+  (when (not js-mozilla-connection)
+    (error "Not connected"))
+  js-mozilla-connection)
+
+(defun js-make-net-buffer (name)
+  "Make a buffer suitable for a network process."
+  (let ((buffer (generate-new-buffer name)))
+    (with-current-buffer buffer
+      (when (fboundp 'set-buffer-multibyte)
+	(set-buffer-multibyte nil))
+      (buffer-disable-undo))
+    buffer))
+
+(defun js-net-connect (port)
+  (let* ((socket (open-network-stream "Mozilla" nil "localhost" port))
+	 (buffer (js-make-net-buffer "*mozilla*")))
+    (set-process-buffer socket buffer)
+    (set-process-filter socket 'js-net-filter)
+    (set-process-sentinel socket 'js-net-sentinel)
+    (when (fboundp 'set-process-coding-system)
+      (set-process-coding-system socket 'no-conversion 'no-conversion))
+    socket))
+
+(defun js-net-send (string connection)
+  (let ((string (concat (js-net-encode-length (length string)) string)))
+    (process-send-string connection (string-make-unibyte string))))
+
+(defun js-net-encode-length (n)
+  (format "%06x" n))
+
+(defun js-net-filter (process string)
+  "Accept output from the socket and input all complete messages."
+  (with-current-buffer (process-buffer process)
+    (save-excursion
+      (goto-char (point-max))
+      (insert string))
+    (goto-char (point-min))
+    (js-process-available-input)))
+
+(defun js-process-available-input ()
+  "Process all complete messages that have arrived from Mozilla."
+  (unwind-protect
+      (when (js-connection)
+	(with-current-buffer (process-buffer (js-connection))
+	  (while (js-net-have-input-p)
+	    (let ((event (condition-case error (js-net-read)
+			   (error (js-net-panic error)))))
+	      (save-current-buffer
+		(js-dispatch-event event))))))
+    (when (js-connection)
+      (with-current-buffer (process-buffer (js-connection))
+	(when (js-net-have-input-p)
+	  (run-at-time 0 nil 'js-process-available-input))))))
+
+(defun js-net-panic (error)
+  (message "net-read error: %S" error)
+  (let ((string (buffer-string)))
+    (ignore-errors
+      (js-disconnect)
+      (kill-buffer (current-buffer)))
+    (ding)
+    (sleep-for 2)
+    (with-current-buffer (generate-new-buffer "*saved-connecton-buffer*")
+      (insert string)
+      (error "PANIC!" error))))
+
+(defun js-net-have-input-p ()
+  "Return true if a complete message is available."
+  (and (>= (buffer-size) 6)
+       (>= (- (buffer-size) 6) (js-net-read-length))))
+
+(defun js-net-read-length ()
+  (string-to-number (buffer-substring (point) (+ (point) 6)) 16))
+
+(defun js-net-read ()
+  (let* ((length (js-net-read-length))
+	 (start (+ 6 (point)))
+         (end (+ start length)))
+    (let ((string (buffer-substring start end)))
+      (prog1 (read string)
+        (delete-region (point-min) end)))))
+
+(defun js-net-sentinel (process message)
+  (message "Mozilla connection closed unexpectedly: %s" message)
+  (when (eq process js-mozilla-connection)
+    (setq js-mozilla-connection nil))
+  (kill-buffer (process-buffer process)))
+
+(defun js-send (term)
+  (js-log-event (list 'send term))
+  (js-net-send (js-term-to-string term) (js-connection)))
+
+(defun js-term-to-string (term)
+  (etypecase term
+    (symbol (concat "'" (symbol-name term) "'"))
+    (string (with-temp-buffer
+	      (let ((print-escape-nonascii t)
+		    (print-escape-newlines t))
+		(prin1 term (current-buffer))
+		(buffer-string))))
+    (number (number-to-string term))
+    (cons (concat "[" (mapconcat 'js-term-to-string term ", ") "]"))))
+
+;;; Event logging
+
+(defvar js-log-events t
+  "*Log protocol events to the *js-events* buffer.")
+ 
+(defvar js-log-buffer-name "*js-events*"
+  "The name of the js event buffer.")
+
+(defun js-log-event (event)
+  "Record the fact that EVENT occurred."
+  (when js-log-events
+    (with-current-buffer (js-events-buffer)
+      ;; trim?
+      (when (> (buffer-size) 100000)
+        (goto-char (/ (buffer-size) 2))
+        (re-search-forward "^(" nil t)
+        (delete-region (point-min) (point)))
+      (goto-char (point-max))
+      (save-excursion
+        (js-pprint-event event (current-buffer)))
+      (goto-char (point-max)))))
+
+(defun js-pprint-event (event buffer)
+  "Pretty print EVENT in BUFFER with limited depth and width."
+  (let ((print-length 20)
+	(print-level 6)
+	(pp-escape-newlines t))
+    (pp event buffer)))
+
+(defun js-events-buffer ()
+  (get-buffer-create js-log-buffer-name))
+
+;;; RPCing
+
+(defvar js-continuations ()
+  "An alist of (ID . FUNCTION) functions waiting for results.")
+
+(defvar js-continuation-counter 0
+  "Counter to generate serial number for continuations.")
+
+(defun js-dispatch-event (event)
+  (js-log-event event)
+  (apply (car event) (cdr event)))
+
+(defun js-eval (term cont)
+  "Evaluate term in Mozilla and call the function CONT with the result."
+  (let ((id (incf js-continuation-counter))
+	(cont (lexical-let ((cont cont) (buffer (current-buffer)))
+		(lambda (status value)
+		  (with-current-buffer (js-buffer-for-eval buffer)
+		    (ecase status
+		      (ok (funcall cont value))
+		      (error (message "Evaluation aborted: %s" value))))))))
+    (push (cons id cont) js-continuations)
+    (js-send `(eval_for_emacs ,term ,id))))
+
+(defun js-buffer-for-eval (saved-buffer)
+  (let ((alive (buffer-name saved-buffer)))
+    (cond (alive saved-buffer)
+	  (t (generate-new-buffer (format "*killed %s*" saved-buffer))))))
+					 
+(defun js-return (id status value)
+  (let ((rec (assq id js-continuations)))
+    (cond (rec (setq js-continuations (delete rec js-continuations))
+	       (funcall (cdr rec) status value))
+	  (t
+	   (error "Unexpected reply: %S %S" id value)))))
+
+(defvar js-wait-tags ())
+
+(defun js-eval-wait (term)
+  "Evaluate TERM in Mozilla and wait until the result is available."
+  (let* ((id (incf js-continuation-counter))
+	 (tag (gensym))
+	 (unwind (lexical-let ((tag tag))
+		   (lambda (status value)
+		     (unless (memq tag js-wait-tags)
+		       (error "Wait-tag not active: %S." tag))
+		     (throw tag (list status value))))))
+    (push (cons id unwind) js-continuations)
+    (js-send `(eval_for_emacs ,term ,id))
+    (destructuring-bind (status value) (js-wait tag)
+      (ecase status
+	(ok value)
+	(error (error "Syncronous evaluation aborted: %s" value))))))
+
+(defun js-wait (wait-tag)
+  (let ((js-wait-tags (cons wait-tag js-wait-tags))
+	(debug-on-quit t)
+	(inhibit-quit nil))
+    (catch wait-tag
+      (while t (accept-process-output nil 0 10000)))))
+
+(defun js-show-result (result)
+  (message "%S" result))
+    
+;;; Evaluation Commands
+
+(defun js-beginning-of-defun ()
+  "Move to the beginning of the current function.
+Point is placed before foo in the folling example:
+
+foo = function (bar)
+{
+ ...
+}"
+  (interactive)
+  (c-beginning-of-defun 1)
+  (beginning-of-line)
+  (when (looking-at "[ \t]*{")
+    (forward-line -1)))
+
+(defconst js-identifier
+  "[a-zA-Z_\\$][a-zA-Z0-9_\\$]*"
+  "Expression for matching Javascript identifiers.")
+
+(defun js-hack-defun (string)
+  "If STRING looks like function <name> { convert it to <name> = function {"
+  (cond ((string-match (concat "^function\\s +\\(" js-identifier "\\)\\s *(")
+		       string)
+	 (format "%s = function %s" (match-string 1 string)
+		 (substring string (position ?\( string))))
+	(t string)))
+		  
+(defun js-eval-defun ()
+  "Evaluate the current function."
+  (interactive)
+  (save-excursion
+    (c-end-of-defun)
+    (let ((end (point)))
+      (js-beginning-of-defun)
+      (let ((string (buffer-substring-no-properties (point) end)))
+	(js-eval `(interactive_eval ,(js-hack-defun string))
+		 (lambda (result) (message "%s" result)))))))
+
+(defun js-interactive-eval (string &optional insertp)
+  (interactive "Mjavascript eval: \nP")
+  (cond (insertp 
+	 (beginning-of-line 2)
+	 (js-eval `(interactive_eval ,string) #'insert))
+	(t 
+	 (js-eval `(interactive_eval ,string) 
+		  (lambda (result) (message "%s" result))))))
+
+(defun js-eval-region (start end &optional insertp)
+  "Eval region in Mozilla.  
+Insert the result in the current buffer when called with a prefix argument."
+  (interactive "r\nP")
+  (js-interactive-eval (buffer-substring-no-properties start end) insertp))
+
+(defun js-eval-current-line (&optional insertp)
+  "Eval the current line.  See `js-eval-region'."
+  (interactive "P")
+  (js-eval-region (line-beginning-position) (line-end-position) insertp))
+
+(defun js-load-file (filename)
+  "Load the javascript file FILENAME in Mozilla."
+  (interactive (list (read-file-name "Load file: " nil nil
+				     nil (file-name-nondirectory 
+					  (buffer-file-name)))))
+  (let ((url (concat "file:" (expand-file-name filename))))
+    (js-eval `(load_file_for_emacs ,url)
+	     (lambda (message)
+	       (message "Loaded: %s" message)))))
+
+
+;;;; Find definitions
+
+(defvar js-find-definition-history-ring (make-ring 20)
+  "History ring recording the definition-finding \"stack\".")
+
+(defun js-push-definition-stack ()
+  "Add MARKER to the edit-definition history stack.
+If MARKER is nil, use the point."
+  (ring-insert-at-beginning js-find-definition-history-ring (point-marker)))
+
+(defun js-pop-find-definition-stack ()
+  "Pop the edit-definition stack and goto the location."
+  (interactive)
+  (unless (ring-empty-p js-find-definition-history-ring)
+    (let* ((marker (ring-remove js-find-definition-history-ring))
+	   (buffer (marker-buffer marker)))
+      (if (buffer-live-p buffer)
+	  (progn (switch-to-buffer buffer)
+		 (goto-char (marker-position marker)))
+        ;; If this buffer was deleted, recurse to try the next one
+        (js-pop-find-definition-stack)))))
+
+(defun js-find-definitions (name)
+  "Lookup the definition of the symbol at point."
+  (interactive (list (js-read-symbol "Name: ")))
+  (js-eval `(find_definitions ,name)
+	   (lexical-let ((name name))
+	     (lambda (defs) (js-show-definitions name defs)))))
+
+(defun js-show-definitions (name defs)
+  (unless (not defs) 
+    (js-push-definition-stack))
+  (cond ((null defs) (message "No definitions for: %s" name) (ding))
+	((null (cdr defs)) (js-goto-definition (car defs)))
+	(t (js-display-multiple-definitions defs))))
+
+(defun js-goto-definition (definition &optional other-window)
+  (destructuring-bind (filename line) definition
+    (let ((buffer (js-find-source-buffer filename)))
+      (cond (other-window (switch-to-buffer-other-window buffer))
+	    (t (switch-to-buffer buffer)))
+      (goto-line line))))
+
+(defun js-find-source-buffer (filename)
+  (cond ((string-match "^file:" filename)
+	 (find-file-noselect (substring filename (length "file:"))))
+	((string-match "^\\(http\\|chrome\\):" filename)
+	 (or (get-buffer filename)
+	     (with-current-buffer (get-buffer-create filename)
+	       (insert (js-eval-wait `(load_source ,filename)))
+	       (not-modified)
+	       (setq buffer-read-only t)
+	       (setq buffer-file-name filename)
+	       (normal-mode)
+	       (js-mode 1)
+	       (current-buffer))))
+	(t (error "cannot resolve url: %s" filename))))
+
+(defun js-display-multiple-definitions (defs)
+  "Display a buffer to browse the list of definitions DEFS." 
+  (with-current-buffer (get-buffer-create "*definitions*")
+    (setq buffer-read-only nil)
+    (erase-buffer)
+    (setq js-old-window-config (current-window-configuration))
+    (let ((keymap (make-sparse-keymap)))
+      (define-key keymap (kbd "RET") 'js-show-definition-other-window)
+      (define-key keymap (kbd "SPC") 'js-pop-to-definition)
+      (define-key keymap [?q] 'js-quit)
+      (use-local-map keymap)
+      (dolist (def defs)
+	(destructuring-bind (file line) def
+	  (let ((start (point)))
+	    (insert (format "%s:%d\n" file line))
+	    (add-text-properties start (1- (point)) `(definition ,def)))))
+      (goto-char (point-min))
+      (setq buffer-read-only t)
+      (let ((w (select-window (display-buffer (current-buffer)))))
+	(shrink-window-if-larger-than-buffer w)))))
+
+(defun js-quit ()
+  "Kill the current buffer and restore the old window configuration."
+  (interactive)
+  (let ((buffer (current-buffer)))
+    (set-window-configuration js-old-window-config)
+    (kill-buffer buffer)))
+
+(defun js-property-at-point (prop)
+  (or (get-text-property (point) prop)
+      (error "No %s at point" prop)))
+
+(defun js-pop-to-definition (definition)
+  "Jump to the definition at point and close the current window."
+  (interactive (list (js-property-at-point 'definition)))
+  (delete-window)
+  (js-goto-definition definition))
+
+(defun js-show-definition-other-window (definition)
+  "Display the defintion at point in window."
+  (interactive (list (js-property-at-point 'definition)))
+  (save-selected-window
+    (js-goto-definition definition t)
+    (let ((overlay (make-overlay (line-beginning-position) 
+				 (line-end-position))))
+      (overlay-put overlay 'face 'secondary-selection)
+      (run-with-timer 0.3 nil 'delete-overlay overlay))))
+ 
+;;; Debugger
+
+(defvar js-debugger-level 0)
+
+(define-derived-mode js-debugger-mode fundamental-mode "jsdbg"
+  "Mode to inspect backtraces.  
+See also `js-toggle-break-on-throw'.
+
+\\{js-debugger-mode-map}"
+  (erase-buffer)
+  (set (make-local-variable 'truncate-lines) t)
+  (set-syntax-table c++-mode-syntax-table))
+
+(let ((m js-debugger-mode-map))
+  (define-key m "v" 'js-debugger-show-source)
+  (define-key m "q" 'js-debugger-quit)
+  (define-key m "t" 'js-debugger-toggle-locals)
+  (define-key m "i" 'js-debugger-inspect-variable))
+
+(defun js-debugger-buffer ()
+  (get-buffer-create "*js-debugger*"))
+
+(defun js-debugger-activate (level)
+  (with-current-buffer (js-debugger-buffer)
+    (unless (equal js-debugger-level level)
+      (with-lexical-bindings (level)
+        (js-eval `(debugger_info_for_emacs 0 1)
+		 (lambda (info)
+		   (apply #'js-debugger-setup level info)))))))
+
+(defun js-debugger-setup (level message backtrace)
+  (with-current-buffer (js-debugger-buffer)
+    (unless (equal js-debugger-level level)
+      (setq buffer-read-only nil)
+      (js-debugger-mode)
+      (js-mode 1)
+      (unless js-old-window-config
+        (setq js-old-window-config  (current-window-configuration)))
+      (setq mode-name (format "js-debugger[%d]" js-debugger-level))
+      (insert message "\n")
+      (insert "\nBacktrace: \n")
+      (save-excursion (js-insert-backtrace backtrace))
+      (setq buffer-read-only t)
+      (pop-to-buffer (current-buffer))
+      (when (and js-wait-tags
+                 (y-or-n-p "Enter recursive edit? "))
+        (message "Entering recursive edit..")
+        (recursive-edit)))))
+
+(defun js-insert-backtrace (backtrace)
+  (mapc #'js-insert-frame backtrace))
+
+(defun js-insert-frame (frame)
+  (destructuring-bind (number text) frame
+    (let ((start (point-marker)))
+      (set-marker-insertion-type start nil)
+      (insert text)
+      (let ((end (point-marker)))
+	(insert "\n")
+	(set-marker-insertion-type end t)
+	(add-text-properties start end 
+			     (list 'frame number 
+				   'text text
+				   'start start 'end end))))))
+
+(defun js-debugger-show-source (frame)
+  "Show the source buffer for the frame at point."
+  (interactive (list (js-property-at-point 'frame)))
+  (js-eval `(frame_source_location ,frame)
+	   (lambda (location)
+	     (destructuring-bind (file baseline line) location
+	       (js-show-definition-other-window  (list file line))))))
+
+(defun js-debugger-quit ()
+  "Exit from the debugger and continue execution."
+  (interactive)
+  (js-eval `(debugger_quit) 
+	   (lambda (x) 
+	     (message "%S" x)
+	     (let ((buffer (current-buffer))) 
+	       (set-window-configuration js-old-window-config)
+	       (kill-buffer buffer)))))
+
+(defun js-debugger-toggle-locals (frame)
+  "Show the local variables for the current frame."
+  (interactive (list (js-property-at-point 'frame)))
+  (let ((inhibit-read-only t))
+      (destructuring-bind (text start end detailsp) 
+	  (loop for p in '(text start end detailsp)
+		collect (get-text-property (point) p))
+	(cond ((not detailsp)
+	       (let ((locals (js-eval-wait `(frame_locals ,frame))))
+		 (goto-char end)
+		 (let ((new-start (point)))
+		   (insert-and-inherit text "\n")
+		   (loop for l in locals for i from 0 
+			 do (js-insert-line-with-props (concat "     " l )
+						       `(local-var ,i)))
+		   (delete-region start new-start)
+		   (put-text-property start end 'detailsp t))))
+	      (t
+	       (goto-char end)
+	       (let ((new-start (point)))
+		 (insert-and-inherit text)
+		 (delete-region start new-start)
+		 (put-text-property start end 'detailsp nil))))
+	(goto-char start))))
+
+(defun js-insert-line-with-props (text props)
+  (let ((start (point)))
+    (insert-and-inherit text)
+    (let ((end (point)))
+      (insert-and-inherit "\n")
+      (add-text-properties start end props))))
+
+(defun js-debugger-inspect-variable (frame var)
+  "Inspect the variable at point."
+  (interactive (list (js-property-at-point 'frame)
+		     (js-property-at-point 'local-var)))
+  (js-eval `(inspect_local_variable ,frame ,var)
+	   'js-open-inspector))
+
+(defun js-toggle-break-on-throw ()
+  "Enable or disable debugging on throws."
+  (interactive)
+  (js-eval `(toggle_break_on_throw) (lambda (m) (message "%s" m))))
+
+

+;;; Inspector
+
+(defvar js-inspect-hist ())
+
+(defun js-inspect (string)
+  "Evalute STRING and inspect the result."
+  (interactive (list (read-from-minibuffer "Inspect value (evaluated): " 
+					   nil nil nil 'js-inspect-hist)))
+  (js-eval `(init_inspector ,string) 'js-open-inspector))
+
+(define-derived-mode js-inspector-mode fundamental-mode "Javascript-Inspector"
+  "Mode to inspect Javascript objects. 
+
+\\{js-debugger-mode-map}"
+  (set-syntax-table java-mode-syntax-table)
+  (set (make-local-variable 'truncate-lines) t)
+  (setq buffer-read-only t))
+
+(let ((m js-inspector-mode-map))
+  (define-key m (kbd "RET") 'js-inspect-part)
+  (define-key m "l" 'js-inspector-last)
+  (define-key m "n" 'js-inspector-next)
+  (define-key m "a" 'js-inspector-apply-part)
+  (define-key m "q" 'js-quit-inspector))
+
+(defun js-inspector-buffer ()
+  (or (get-buffer "*Javascript Inspector*")
+      (with-current-buffer (get-buffer-create "*Javascript Inspector*")
+	(setq js-inspector-mark-stack '())
+	(js-inspector-mode)
+	(js-mode 1)
+        (setq js-old-window-config (current-window-configuration))
+	(current-buffer))))
+
+(defun js-open-inspector (parts &optional point)
+  (with-current-buffer (js-inspector-buffer)
+    (let ((inhibit-read-only t))
+      (erase-buffer)
+      (destructuring-bind (printed type lines) parts
+	(insert printed "\n")
+	(insert "   [type: " type "]\n\n")
+	(save-excursion
+	  (loop for (label text) in lines for i from 0 
+		do (js-insert-line-with-props (concat label ": " text)
+					      `(part ,i))))
+	(pop-to-buffer (current-buffer))
+	(when point 
+	  (goto-char (min (point-max) point)))))))
+
+(defun js-inspect-part (id)
+  "Inspect the slot at point."
+  (interactive (list (js-property-at-point 'part)))
+  (js-eval `(inspect_nth_part ,id) 'js-open-inspector)
+  (push (point) js-inspector-mark-stack))
+
+(defun js-inspector-next ()
+  "Inspect the next object in the history."
+  (interactive)
+  (js-eval `(inspector_next)
+	   (lambda (parts) 
+	     (cond ((eq parts 'false)
+		    (message "No next object")
+		    (ding))
+		   (t
+		    (push (point) js-inspector-mark-stack)
+		    (js-open-inspector parts))))))
+
+(defun js-inspector-last ()
+  "Inspect the previous object."
+  (interactive)
+  (js-eval `(inspector_pop)
+	   (lambda (result)
+	     (cond ((eq result 'false)
+		    (message "No previous object")
+		    (ding))
+		   (t
+		    (let ((point (pop js-inspector-mark-stack)))
+		      (js-open-inspector result point)))))))
+
+(defun js-inspector-apply-part (number &optional args)
+  "Call the function at the current slot and inspect the result.
+Call this command with a prefix argument to supply arguments."
+  (interactive (list (js-property-at-point 'part)
+		     (if current-prefix-arg
+			 (read-from-minibuffer "Argument vector: " "[]"))))
+  (let ((args (or args "[]")))
+    (js-eval `(inspector_apply_part ,number ,args) 'js-open-inspector)
+    (push (point) js-inspector-mark-stack)))
+
+(defun js-quit-inspector ()
+  "Close the inspector."
+  (interactive)
+  (js-eval `(quit_inspector)
+	   (lambda (x)
+	     (set-window-configuration js-old-window-config)
+	     (kill-buffer (current-buffer)))))
+
+;;; Portability kludges
+
+(unless (fboundp 'substring-no-properties)
+  (defun substring-no-properties (string &optional start end)
+    (let* ((start (or start 0))
+	   (end (or end (length string)))
+	   (string (substring string start end)))
+      (set-text-properties start end nil string)
+      string)))
+
+(unless (fboundp 'string-make-unibyte)
+  (defalias 'string-make-unibyte #'identity))
+
+;;;
+
+(run-hooks 'js-load-hook)
+
+(provide 'js-mode)
+
+;;; js-mode.el ends here


Property changes on: branches/trunk-reorg/thirdparty/emacs/js-mode.el
___________________________________________________________________
Name: svn:executable
   + *

Added: branches/trunk-reorg/thirdparty/emacs/shellserver.xpi
===================================================================
(Binary files differ)


Property changes on: branches/trunk-reorg/thirdparty/emacs/shellserver.xpi
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream




More information about the Bknr-cvs mailing list