I will take you through the following steps in order to get on-the-fly spell checking in your Emacs with flymake-js while coding JavaScript.

What is Flymake?
While others idolize those fancy IDEs just because of the automatic syntax checking as you type, Flymake is an Emacs mode that do the same. „It runs the syntax check tool [...] in the background, passing it a temporary copy of the current buffer and parses the output for known error/warning message patterns”. Watch Emacs Flymake under power!
Though it’s trivial to get a command line tool whilst coding in C, Perl, Java, etc., only a few knows that you can debug your JavaScript code outside of the browser.
How to debug JavaScript from command line?
Rhino is an open source JavaScript engine, developed in Java. It comes with all the features of JavaScript 1.5, and contains a ”JavaScript shell for executing JavaScript scripts„. So do we need Firebug no more? Of course not. Rhino allows the running of your JavaScript code, but that’s all. It is not a web browser, it does not understand all the objects provided by that. So the question comes straight.
How to simulate web browser environment?
The most I love in the open source world that everything is ready for you. You just need to reach for it.
John Resig, in Bringing the Browser to the Server, demonstrates his wrapper for Rhino, that „is a good-enough browser/DOM environment, written in JavaScript„. It does exactly what we need. Provides all those objects (window, document, etc.) that crucial for syntax checking a web browser dependent code.
Now that we’ve got a browser environment on top of Rhino and Flymake. See how to glue them together.
Catching error messages in Emacs, introducing flymake-js
-
At first, install all the required packages and libs we need further on. Grab Rhino from the Mozilla project page or check for binary packages of your distribution. Calling the JAR puts you in the Rhino JavaScript shell.
java -jar ~/dev/lib/rhino-1.6R6.jar Rhino 1.6 release 6 2007 07 26 js> - To setup Flymake, wget flymake.el where you store your Emacs modes. No more settings needed at this point.
- Create a folder where you will store some project files. Download John’s env.js and place it there.
-
Thereinafter let’s write little wrapper that builds the browser environment, and when it’s ready, loads the script we want to syntax check. Save the following to the newly created directory as
rhino.js, and customize variableproject_folderto fit your needs.// Where you store your files var project_folder = '/home/gabor/dev/slink/js/'; // Browser environment wrapper over Rhino load(project_folder + 'env.js'); // For DOM constructing window.location = project_folder + 'blank.html'; var my_script = arguments[0]; // If DOM ready window.onload = function(){ // Avoid recursive inclusion if ("rhino_flymake.js" != my_script) { load(my_script); } } -
To finish this step, we need to create a null template HTML for building DOM.
<html> <head></head> <body></body> </html> -
Now get your favourite JS code and test your brand new command line install:
java -jar ~/src/yuicompressor-1.0/lib/rhino-1.6R6.jar rhino.js rhino-flymake.js - The last task to write a JavaScript extension for Flymake. Com’on.
;; Flymake JS mode (require 'flymake) (defconst flymake-allowed-js-file-name-masks '( ("\\.json$" flymake-js-init) ("\\.js$" flymake-js-init)) "Filename extensions that switch on flymake-js mode syntax checks") (defconst flymake-js-err-line-pattern-re '( ("^js: \"\\(.+\\)\", line \\([0-9]+\\): \\(.+\\)$" 1 2 nil 3) ("^js: uncaught JavaScript \\(.+\\)$" nil nil nil 1) ) "Regexp matching JavaScript error messages") (defun flymake-js-init () (let* ((temp-file (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace)) (local-file (file-relative-name temp-file (file-name-directory buffer-file-name)))) (list "java" (list "-jar" "/home/gabor/src/yuicompressor-1.0/lib/rhino-1.6R6.jar" "/home/gabor/dev/slink/js/rhino.js" local-file)))) (defun flymake-js-load () (setq flymake-allowed-file-name-masks (append flymake-allowed-file-name-masks flymake-allowed-js-file-name-masks)) (setq flymake-err-line-patterns (append flymake-err-line-patterns flymake-js-err-line-pattern-re)) (flymake-mode t) (local-set-key (kbd "C-c d") 'flymake-display-err-menu-for-current-line)) (provide 'flymake-js)Save it as
flymake-js.elunder your Emacs mode folder, and add a hook for the minor mode you edit JavaScript files with. In our case that’s java-mode, so I put the following in my.emacs.(require 'flymake-js) (add-hook 'java-mode-hook 'flymake-js-load) - We’re finished! Bring up your Emacs, load a JS script file, make some mistakes, and get the error messages on-the-fly.
What’s not flymake-js?
Flymake-js only checks for valid syntax but it does not analyize your code, cannot throw runtime errors. Using flymake-js completes, and does not replace Firebug.
John’s env.js on top of Rhino may have some limitations.
Anyway, flymake-js is not a web browser.
Known issues
If runtime exception was thrown, line number is unknown, hence flymake-js shows that error was found at line 1.
Commit other issues via flymake-js Google Code project page.
Comments are welcome at DZone.