1 ;;; flymake-js.el --- Flymake setup for javascript files
3 ;; Author: Lennart Borgman
4 ;; Created: Sun Dec 02 07:52:52 2007
11 ;; Features that might be required by this library:
15 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
19 ;; This library provides basic setup for using `flymake-mode' with
20 ;; javascript files. To use this you must have a javascript
21 ;; installed. There are (at least) two free javascript engines (both
22 ;; from Mozill) you can use, Rhino (implemented in Java) or
23 ;; SpiderMonkey (implemented in C). Both are supported in this
26 ;; I have not been able to find binaries for SpiderMonkeys to
27 ;; download. However the Rhino engine seems fast enough and is easy to
28 ;; install. You find them at
30 ;; http://www.mozilla.org/rhino/
31 ;; http://www.mozilla.org/js/spidermonkey/
33 ;; Put this file in your Emacs `load-path' and then in .emacs
35 ;; (require 'flymake-js)
38 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
43 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
45 ;; This program is free software; you can redistribute it and/or
46 ;; modify it under the terms of the GNU General Public License as
47 ;; published by the Free Software Foundation; either version 2, or
48 ;; (at your option) any later version.
50 ;; This program is distributed in the hope that it will be useful,
51 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
52 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
53 ;; General Public License for more details.
55 ;; You should have received a copy of the GNU General Public License
56 ;; along with this program; see the file COPYING. If not, write to
57 ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
58 ;; Floor, Boston, MA 02110-1301, USA.
60 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
68 (defconst flymake-js-dir
69 (file-name-directory (or load-file-name
70 (when (boundp 'bytecomp-filename) bytecomp-filename)
72 "Installation directory for flymake-js.")
75 (defgroup flymake-js nil
76 "Customization group for flymake for javascript."
79 (defcustom flymake-allowed-js-file-name-masks '(("\\.json\\'" flymake-js-init)
80 ("\\.js\\'" flymake-js-init))
81 "Filename extensions that switch on js syntax checks."
82 :type '(repeat (list (regexp :tag "File name regexp")
83 (function :tag "Init function")
84 (choice (const :tag "No cleanup function" nil)
85 (function :tag "Cleanup function"))))
89 (defvar flymake-js-err-line-pattern-re
90 '(;; These pattern are probably for Rhino:
91 ("^js: \"\\(.+\\)\", line \\([0-9]+\\): \\(.+\\)$" 1 2 nil 3)
92 ("^js: uncaught JavaScript \\(.+\\)$" nil nil nil 1)
93 ;; For Rhino with jslint.js
94 ("^Lint at line \\([[:digit:]]+\\) character \\([[:digit:]]+\\): \\(.+\\)$" nil 1 2 3)
95 ;; These pattern are probably for SpiderMonkey:
96 ("^\\(.+\\)\:\\([0-9]+\\)\: \\(SyntaxError\:.+\\)\:$" 1 2 nil 3)
97 ("^\\(.+\\)\:\\([0-9]+\\)\: \\(strict warning: trailing comma.+\\)\:$" 1 2 nil 3))
98 "Regexp matching JavaScript error messages")
100 (defcustom flymake-js-rhino-jar "/path/to/js.jar"
101 "Path to Rihno jar file.
102 Download and install Rhino JavaScript engine from
104 URL `http://www.mozilla.org/rhino/'
106 This variable should point to the file js.jar that is in the top
107 directory of the Rhino dir tree. \(It was differently named
108 earlier and might perhaps be renamed again.)"
109 :type '(file :must-match t)
112 ;;(setq flymake-log-level 3)
113 ;;(setq flymake-js-rhino-use-jslint nil)
114 (defcustom flymake-js-rhino-use-jslint nil
115 "Use jslint.js if this is non-nil.
116 jslint.js will give you warnings about style things like indentation too."
120 (defcustom flymake-js-rhino-js (expand-file-name "rhino.js" flymake-js-dir)
122 Only used if `flymake-js-rhino-use-jslint' is nil.
124 This file and env.js must be placed in the same directory. Default
127 Those files comes with Rhino, see `flymake-js-rhino-jar'."
128 :type '(file :must-match t)
131 (defcustom flymake-js-rhino-jslint (expand-file-name "jslint.js" flymake-js-dir)
133 Only used if `flymake-js-rhino-use-jslint' is t.
135 If you do not have this file you can download it from URL
136 `http://www.jslint.com/rhino/jslint.js'. I had to change quit(2)
137 to quit(0) in it \(which seems like a bug in `flymake-mode' to
139 :type '(file :must-match t)
142 ;;(flymake-js-check-rhino-js)
143 (defun flymake-js-check-rhino-js ()
144 "Checks that the path to env.js is ok."
145 (with-current-buffer (find-file-noselect flymake-js-rhino-js)
146 (let* ((proj-folder (file-name-as-directory (file-name-directory (buffer-file-name))))
147 (proj-line (concat "var project_folder = 'file:///" proj-folder "';"))
148 (proj-line-re "^\\W*var\\W+project_folder\\W*=\\W*"))
151 (goto-char (point-max))
152 (if (re-search-backward proj-line-re nil t)
153 (let ((beg (line-beginning-position))
154 (end (line-end-position)))
155 (unless (string= (buffer-substring-no-properties beg end)
157 (delete-region beg end)
159 (basic-save-buffer)))
160 (goto-char (point-min))
161 (insert proj-line "\n")
162 (basic-save-buffer))))))
164 (defcustom flymake-js-engine 'rhino
165 "Javascript engine to use.
166 You may have to restart Emacs after changing this - if you can
167 not figure out what buffers and processes to kill.
169 I have only been able to test Rhino since I do not have
171 :type '(choice (const :tag "Rhino" rhino)
172 (const :tag "SpiderMonkey" spidermonkey))
175 (defun flymake-js-init ()
176 (message "running flymake-js-init")
177 (let* ((temp-file (flymake-init-create-temp-buffer-copy
178 'flymake-create-temp-inplace))
179 (local-file (file-relative-name
181 (file-name-directory buffer-file-name))))
182 (flymake-js-check-has-engine)
184 ((eq flymake-js-engine 'rhino)
185 (list "java" (list "-jar" flymake-js-rhino-jar
186 (if flymake-js-rhino-use-jslint
187 flymake-js-rhino-jslint
190 ((eq flymake-js-engine 'spidermonkey)
191 (list "js" (list "-s" local-file)))
193 (error "Bad value: %s" flymake-js-engine)))))
195 (defvar flymake-js-has-engine nil)
197 (defun flymake-js-check-has-engine ()
198 "Check for the needed files."
199 (if flymake-js-has-engine
203 ((eq flymake-js-engine 'rhino)
204 (unless (executable-find "java")
205 (error "Could not find java executable"))
206 (unless (file-exists-p flymake-js-rhino-jar)
207 (error "Could not find file %s\n\nPlease customize flymake-js-rhino-jar\n"
208 flymake-js-rhino-jar))
209 (if flymake-js-rhino-use-jslint
210 (unless (file-exists-p flymake-js-rhino-jslint)
211 (error "Could not find file %s" flymake-js-rhino-jslint))
212 (unless (file-exists-p flymake-js-rhino-js)
213 (error "Could not find file %s" flymake-js-rhino-js))
214 (flymake-js-check-rhino-js)))
216 ((eq flymake-js-engine 'spidermonkey)
217 (unless (executable-find "js")
218 (error "Could not find js program")))
220 (error "Bad value: %s" flymake-js-engine)))
221 (setq flymake-js-has-engine t)))
224 (defun flymake-js-load ()
225 (dolist (rec flymake-allowed-js-file-name-masks)
226 (add-to-list 'flymake-allowed-file-name-masks rec))
227 (dolist (rec flymake-js-err-line-pattern-re)
228 (add-to-list 'flymake-err-line-patterns rec)))
230 ;;(eval-after-load 'javascript (flymake-js-load))
232 (provide 'flymake-js)
233 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
234 ;;; flymake-js.el<2> ends here