1 ;;; javascript-mode.el --- major mode for editing JavaScript code
3 ;; Copyright (C) 1997-2001 Steven Champeon
4 ;; 2002-2006 Ville Skyttä
6 ;; Author: 1997 Steven Champeon <schampeo@hesketh.com>
7 ;; Maintainer: Ville Skyttä <scop@xemacs.org>
8 ;; Keywords: languages javascript
10 ;; This file is part of XEmacs.
12 ;; XEmacs is free software; you can redistribute it and/or modify it
13 ;; under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; XEmacs is distributed in the hope that it will be useful, but
18 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 ;; General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with XEmacs; see the file COPYING. If not, write to
24 ;; the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
27 ;; Synched up with: not in GNU Emacs.
31 ;; javascript-mode was originally derived from java-cust.el
32 ;; (by Jonathan Payne) by Steven Champeon. It has been modified
33 ;; a lot afterwards by Ville Skyttä.
36 ;; Sreng Truong (bug fix for 21.1)
37 ;; Sebastian Delmont (fix for prototype function indentation problems)
38 ;; Stefan Schlee (GNU Emacs compatibility fixes)
40 ;; Tsirkin Evgeny (regexp improvement ideas)
43 ;; - Multiple font-lock/highlight levels.
44 ;; - Investigate if Semantic Bovinator should be used.
45 ;; - Check syntax-table stuff.
58 ;; ------------------------------------------------------------------------ ;;
60 (defconst javascript-mode-version "1.10" "Version of `javascript-mode'.")
62 ;; ------------------------------------------------------------------------ ;;
64 (defgroup javascript nil
65 "Major mode for editing JavaScript code."
68 :prefix "javascript-")
70 (defcustom javascript-mode-hook nil
71 "Hook for customizing `javascript-mode'."
75 (defgroup javascript-shell nil
76 "JavaScript shell options."
78 :prefix "javascript-shell-")
80 (defcustom javascript-shell-command "jsshell"
81 "*Command for starting `javascript-shell'.
82 Set arguments for this command in `javascript-shell-command-args'."
84 :group 'javascript-shell)
86 (defcustom javascript-shell-command-args '()
87 "*Command line arguments for `javascript-shell-command'."
88 :type '(repeat (string :tag "Argument"))
89 :group 'javascript-shell)
91 (defcustom javascript-shell-prompt-pattern "^js> *"
92 "*JavaScript shell prompt pattern."
94 :group 'javascript-shell)
96 (defcustom javascript-shell-mode-hook nil
97 "Hook for customizing `javascript-shell-mode'."
99 :group 'javascript-shell)
101 ;; ------------------------------------------------------------------------ ;;
103 (defvar javascript-mode-abbrev-table nil
104 "Abbrev table in use in `javascript-mode' buffers.")
105 (define-abbrev-table 'javascript-mode-abbrev-table ())
107 ;; ------------------------------------------------------------------------ ;;
109 (defvar javascript-mode-map (c-make-inherited-keymap)
110 "Keymap used in `javascript-mode' buffers.")
112 (defvar javascript-menu nil)
113 (easy-menu-define javascript-menu javascript-mode-map
114 "JavaScript Mode Commands" (c-mode-menu "JavaScript"))
116 ;; ------------------------------------------------------------------------ ;;
118 ;; Reserved words in JavaScript.
119 (defconst javascript-reserved-words
183 "Expression for matching reserved words in `javascript-mode' buffers.
185 From Core JavaScript Reference 1.5, Reserved Words:
186 <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Reserved_Words>")
189 ;; JavaScript identifiers
190 ;; This one is intentionally not too strict...
191 (defconst javascript-identifier
192 "[a-zA-Z_\\$][a-zA-Z0-9_\\$]*"
193 "Expression for matching identifiers in `javascript-mode' buffers.
195 From Core JavaScript Guide 1.5, Core Language Features:
196 <http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Guide:About:Core_Language_Features>")
198 ;; ------------------------------------------------------------------------ ;;
200 ;; Font lock keywords etc
202 ;; eg. function foo(bar, quux)
203 (defconst javascript-function-re
204 (concat "\\(^\\|[ \t;{]\\)"
207 "\\(" javascript-identifier "\\.\\)*"
208 javascript-identifier
210 "Regular expression for matching \"normal\" function declarations.")
212 ;; eg. foo: function(bar, quux)
213 (defconst javascript-property-function-re
214 (concat "\\(^\\|[ \t;{]+\\)"
216 "\\(" javascript-identifier "\\.\\)*"
217 javascript-identifier
220 "\\(new[ \t]+Function\\|function\\)"
222 "Regular expression for matching property style function declarations.")
224 ;; eg. foo.bar.quux = function(baz)
225 (defconst javascript-prototype-function-re
226 (concat "\\(^\\|[ \t;{]+\\)"
228 "\\(" javascript-identifier "\\.\\)*"
229 javascript-identifier
232 "\\(new[ \t]+Function\\|function\\)"
234 "Regular expression for matching prototype style function declarations.")
236 (defconst javascript-variable-re
237 (concat "\\(^\\|[ \t;{(]\\)\\(const\\|var\\)[ \t]+"
239 javascript-identifier
241 "Regular expression for matching variables.")
243 (defconst javascript-font-lock-keywords
248 "\\(^\\|[ \t;{(]\\)\\("
249 javascript-reserved-words
251 '(2 'font-lock-keyword-face))
253 ;; Function declarations.
254 (cons javascript-function-re '(2 'font-lock-function-name-face))
255 (cons javascript-property-function-re '(2 'font-lock-function-name-face))
256 (cons javascript-prototype-function-re '(2 'font-lock-function-name-face))
257 ;; This would catch both declarations and calls.
259 ; "\\(^\\|[ \t.;{(]\\)\\("
260 ; javascript-identifier
262 ; '(2 'font-lock-function-name-face))
264 ;; Variables and constants.
265 (cons javascript-variable-re '(3 'font-lock-variable-name-face))
266 ;; This would catch more of them and properties as well.
268 ; "\\(^\\|[ \t(\\[\\.{;]\\)\\("
269 ; javascript-identifier
271 ; '(2 'font-lock-variable-name-face))
274 "Highlighting rules for `javascript-mode' buffers.")
276 ;; ------------------------------------------------------------------------ ;;
278 (defvar javascript-imenu-generic-expression
279 `((nil ,javascript-function-re 2)
280 (nil ,javascript-property-function-re 2)
281 (nil ,javascript-prototype-function-re 2)
282 ;; ("Variables" ,javascript-variable-re 3)
284 "Imenu generic expression for JavaScript mode.
285 See `imenu-generic-expression'.")
287 ;; ------------------------------------------------------------------------ ;;
290 (defun javascript-mode ()
291 "Major mode for editing JavaScript code.
293 See the documentation for `c++-mode': JavaScript mode is an extension of it.
294 Use the hook `javascript-mode-hook' to execute custom code when entering
297 \\{javascript-mode-map}"
300 (let ((current-c++-mode-hook (and (boundp 'c++-mode-hook) c++-mode-hook)))
302 ;; Temporarily disable the c++-mode hook; don't wanna run
303 ;; it when loading up c++-mode.
304 (setq c++-mode-hook nil)
308 (setq major-mode 'javascript-mode mode-name "JavaScript")
309 (use-local-map javascript-mode-map)
310 (setq local-abbrev-table javascript-mode-abbrev-table)
311 (c-set-offset 'inher-cont '+)
313 ;; Change menu name. Kudos to Geert Ribbers and Igor Rayak.
314 (easy-menu-remove '("C++"))
315 (easy-menu-add javascript-menu)
317 ;; GNU Emacs reportedly needs this for font locking to work properly.
318 (unless (featurep 'xemacs)
319 (set (make-local-variable 'font-lock-defaults)
320 '(javascript-font-lock-keywords nil nil)))
322 ;; cc-mode does not handle JavaScript prototype function declarations well.
323 ;; Thanks to Sebastian Delmont.
324 (set (make-local-variable 'c-lambda-key) "function")
325 (c-set-offset 'inlambda 0)
328 (set (make-local-variable 'imenu-generic-expression)
329 javascript-imenu-generic-expression)
331 ;; Restore the original c++-mode-hook.
332 (setq c++-mode-hook current-c++-mode-hook)
334 (run-hooks 'javascript-mode-hook)))
336 ;; ------------------------------------------------------------------------ ;;
339 (defun javascript-shell ()
340 "Run a JavaScript shell as an inferior process.
342 Use the `javascript-shell-command' variable to set the command and
343 `javascript-shell-command-args' for its arguments to specify the
344 command line that invokes your preferred JavaScript shell.
346 Free JavaScript shell implementations are available for example from
347 <http://www.mozilla.org/js/>.
349 Usage examples: command arguments
350 Mozilla SpiderMonkey jsshell
351 Mozilla Rhino java -jar /path/to/js.jar"
355 (unless (comint-check-proc "*JavaScript*")
357 (apply 'make-comint "JavaScript"
358 javascript-shell-command nil javascript-shell-command-args))
359 (javascript-shell-mode)
362 (pop-to-buffer "*JavaScript*")
366 (defun javascript-shell-mode ()
367 "Major mode for interacting with a JavaScript shell."
369 (setq comint-prompt-regexp javascript-shell-prompt-pattern)
370 (setq mode-name 'javascript-shell-mode)
371 (setq mode-name "JavaScript Shell")
372 (setq mode-line-process '(":%s"))
373 (run-hooks 'javascript-shell-mode-hook)
376 ;; ------------------------------------------------------------------------ ;;
378 ;;;###autoload(add-to-list 'auto-mode-alist '("\\.js$" . javascript-mode))
379 ;;;###autoload(add-to-list 'auto-mode-alist '("\\.pac$" . javascript-mode))
382 (if (fboundp 'speedbar-add-supported-extension)
383 (speedbar-add-supported-extension '(".js" ".pac")))
385 ;; ------------------------------------------------------------------------ ;;
387 (provide 'javascript-mode)
389 ;;; javascript-mode.el ends here