Install and use the mooz fork of js2-mode

Update (2013 March) : Consider this article deprecated. The ELPA version of js2-mode now has features of mooz’s fork. Do M-x list-packages RET and then install js2-mode from there. See my js2-mode setup recommendations.

Steve Yegge released a JavaScript mode for Emacs called js2-mode in 2008. Its selling point over other JavaScript modes was its built-in JavaScript parser, syntax error detection and indentation based on the parser. Its biggest con was that it enforced an unpopular indentation style. But there’s a fork fixing that:

mooz/js2-mode · GitHub

If you want to try js2-mode, you should use the mooz fork instead of the original js2-mode. The link to the original js2-mode follows:

js2-mode – Enhanced JavaScript IDE Emacs Mode – Google Project Hosting

The js2-mode included in the default emacs package archive is Steve Yegge’s js2-mode version 20090814 as of now (2012 March). So if you installed that js2-mode package, you will have to either disable or override the package in order to use the mooz fork version instead.

Installation of the mooz fork:

1. Download and decompress the ZIP file linked from the GitHub page for the mooz fork. Move the decompressed directory to where you like it to be.

direct link to the ZIP file

2. Open the file js2-mode.el in Emacs and do M-x byte-compile-file RET to byte compile the el file.

3. With the js2-mode.el buffer open, do C-h v default-directory RET and copy the directory path shown.

4. Add the following code to your dotemacs file. Replace "PATH-TO-FORK-DIR" with the directory path you have copied.

(add-to-list 'load-path "PATH-TO-FORK-DIR")
(autoload 'js2-mode "js2-mode" nil t)
(add-to-list 'auto-mode-alist '("\\.js$" . js2-mode))

5. To check if the installation was successful, restart Emacs, open a new JavaScript file. Press C-h m and you should see the following line:

JavaScript-IDE mode defined in `js2-mode.el'

Now write the following:

var chunky = 1,
bacon = 2;
setTimeout(function(){
window.alert(chunky + bacon);
}, 3000);

Select the whole region in the buffer and press C-M-\ (or M-x indent-region) or TAB (or M-x indent-for-tab-command) to see the code indented as:

var chunky = 1,
    bacon = 2;
setTimeout(function(){
    window.alert(chunky + bacon);
}, 3000);

If the code gets indended like that, then it means that the fork version is successfully loaded. If you were using the original js2-mode, the code would be indented as:

var chunky = 1,
bacon = 2;
setTimeout(function(){
               window.alert(chunky + bacon);
           }, 3000);

If that’s what you prefer, the fork version lets you have that by setting js2-consistent-level-indent-inner-bracket-p and js2-pretty-multiline-decl-indentation-p to nil. Enter M-x customize-group RET js2-mode to customizer further.

Installation troubles:

1. If you followed the installation steps and opened a new JavaScript file only to see the buffer still getting associated with some other JavaScript mode, the culprit is probably nXHTML. In that case, you can add:

/* -*- mode:js2 -*- */

as the first line of the JavaScript file you want to edit in js2-mode. Here is a quote from the comment section in js2-mode.el:

This mode does not yet work with “multi-mode” modes such as `mmm-mode’ and `mumamo’, although it could be made to do so with some effort. This means that `js2-mode’ is currently only useful for editing JavaScript files, and not for editing JavaScript within tags or templates.

Does anybody know a fork of js2-mode that works with “multi-mode” modes?

2. If you are using a package that depends on the js2-mode package, you cannot disable the js2-mode package and JavaScript files may open in the Steve Yegge’s original js2-mode instead of the fork version you have installed. M-x locate-library RET js2-mode shows which js2-mode is going to be loaded. In order for the fork version to load, the path to the directory containing the fork version should come before that of the package version in load-path. One way to ensure that is to make sure that the line

(add-to-list 'load-path "PATH-TO-FORK-DIR")

executes only after (package-initialize) is run. If you are one of those people who prefer to put the line (package-initialize) at the end, not the beginning, of dotemacs, you can put the following anywhere in dotemacs:

;; got from esk-eval-after-init
(defun my-eval-after-init (form)
  (let ((func (list 'lambda nil form)))
    (add-hook 'after-init-hook func)
    (when after-init-time
      (eval form))))

(let ((path "PATH-TO-FORK-DIR"))
  (when (file-exists-p path)
    (setq mooz-js2-mode-directory path)
    (my-eval-after-init
     '(add-to-list 'load-path mooz-js2-mode-directory))))
This entry was posted in Emacs and tagged , . Bookmark the permalink.

3 Responses to Install and use the mooz fork of js2-mode

  1. Pingback: js2-mode setup recommendation | Yoo Box

  2. nehalecky says:

    Hi Jisang,

    Thanks for your writeup. I’ve been working lately in with the Google Maps API and wanted a bit more than the default JS mode that exists by default. I tried implementing what you did here this on my local machine running GNU Emacs 24.2.1, but no luck. In short, opening a `.js` file doesn’t cause Emacs to recognize and implement/run the js2-mode.

    No errors reported, just emacs defaults to using a general mode so I don’t have *any* of the fun features (syntax highlighting, etc.). This hook to `.js` files is provided via the line:
    `(add-to-list ‘auto-mode-alist ‘(“\\.js$” . js2-mode))`
    yet I can’t figure out why this wouldn’t be working for me?

    Any thoughts you might have would be greatly appreciated. Thanks again for the notes.
    Best,
    Nicholaus

    • Jisang Yoo says:

      have you looked into the value of auto-mode-alist to see if there are other entries set for js files? what do you get when you evaluate:

      (require 'cl)
      (remove-if-not
       (lambda (elt)
         (let ((case-fold-search t))
           (string-match-p (rx "js") (car elt))))
       auto-mode-alist)
      

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s