Let’s skip right to the chase: I recommend using Steve Yegge’s js2 mode.

If you want to read about the other options and how they compared with one another in September 2005, read on!

You may also be interested in other things I’ve written about Emacs or on JavaScript.

If you find yourself doing substantial hacking on complicated websites, you’ll probably find yourself needing a decent major mode for editing JavaScript. There are at least six different JavaScript major modes out there — which one should you use? Let’s take a look at them!

A survey of the various JavaScript major modes

generic-x.el (which comes with Emacs) contains javascript-generic-mode, which doesn’t handle indentation well, and fails to correctly highlight C-style (/* … */) comments. But it’s fine for short-term use: since it ships with Emacs, it’s already there when you need it.

To enable it, add (require 'generic-x) to ~/.emacs. This will automatically associate files with .js extensions with javascript-generic-mode.

Peter Kruse’s javascript-mode.el is antiquated. It hasn’t been updated in many years, and relies on hilit19, an obsolete syntax highlighting library. Definitely not recommended.

My recommendation: Karl Landström’s javascript.el appears to be the nicest JavaScript mode out there. It handles indentation well, and both C- and C++-style (// …) comments. A winner! To use, place javascript.el in a directory inside load-path and add the following to your ~/.emacs:

(autoload 'javascript-mode "javascript" nil t)
(add-to-list 'auto-mode-alist '("\\.js\\'" . javascript-mode))

Joost Diepenmaat has a slight tweak of Karl’s mode which contains a few font-lock fixes for quoted strings and regular expressions. I haven’t tried it myself.

There’s also ecmascript-mode.el, which is a derived mode from java-mode. It doesn’t appear to do anything that javascript.el doesn’t do, and it unconditionally makes font-lock-builtin-face bold, regardless of your personal settings. Thanks to krupan and Mathias for the link.

MozRepl comes with its own js-mode.el, which appears to be a very minimal variant on cc-mode. Thanks to RetroJ for pointing this out.

In addition to all of the above, there’s the javascript-mode.el which comes with XEmacs, which I’m told works in Emacs as well (and is even bundled with Aquamacs). Thanks to Reed and Xah for the link.

Robustness tip: simple failover

Say you’ve installed javascript.el on machine A but not on machine B. Ideally, your ~/.emacs file should detect if javascript.el is installed: if it is, it should use it, but if it isn’t, it should fall back on javascript-generic-mode from generic-x.el. This is pretty easy stuff. First, require generic-x as above. Then check for the presence of javascript.el, and configure it if it’s present:

(require 'generic-x)

(when (locate-library "javascript")
  (autoload 'javascript-mode "javascript" nil t)
  (add-to-list 'auto-mode-alist '("\\.js\\'" . javascript-mode)))

This way, you can copy your ~/.emacs file to some other machine, and you know it won’t break.

Comments

  1. Here's how I do thus and such only if a particular library is available:

    (defmacro with-library (symbol &rest body)
      ;(declare (indent 1))
      `(condition-case nil
           (progn
             (require ',symbol)
             ,@body)
    
         (error (message  "I guess we don't have %s available." ',symbol)
                nil)))

    so your example would become

    (with-library javascript-mode
      (add-to-list 'auto-mode-alist '("\\.js\\'" . javascript-mode)))

    Eric Hanchrow, 13 October 2005

  2. Thanks, Eric.

    Two things: Using locate-library with autoloads instead of require means that the library is only loaded when I actually go to use it. But, in the cases where you want to use require, it takes an optional NOERROR argument, so you don’t need your condition-case wrapper.

    Emacs is hard. Let’s go shopping! :)

    hober, 13 October 2005

  3. krupan

    When I copy and pasted your code snippet, the ' characters all came out as the string \u2018. What's up with that?

    krupan, 9 January 2006

  4. krupan

    Oooo, I just found ecmascript-mode. It claims to be based on java-mode, and it highlights a lot more keywords that the above mentioned modes:

    http://www.emacswiki.org/cgi-bin/wiki/ECMAScriptMode

    krupan, 9 January 2006

  5. Mathias

    A fallback can also be to use java-mode. It indents correctly most of the time, anyway.

    Mathias, 9 January 2006

  6. krupan — re: \u2018, it appears to be a mis-feature of WordPress, which I’ll attempt to track down and kill. Thanks for the heads-up!

    hober, 9 January 2006

  7. The link for javascript.el seems to have changed. It is now:

    http://web.comhem.se/~u83406637/emacs/javascript.el

    Jonathan Arnold, 28 February 2006

  8. Thanks, Jonathan, I've updated the article's link to javascript.el.

    hober, 28 February 2006

  9. Reed Sheridan

    I had been using the javascript mode from Xemacs in GNU Emacs.

    http://cvs.xemacs.org/viewcvs.cgi/XEmacs/packages/xemacs-packages/prog-modes/javascript-mode.el?rev=1.12&content-type=text/vnd.viewcvs-markup

    I might have had to tweak something to get it to work, I don't remember, but I think it basically works in GNU Emacs. It's not as nice as javascript.el, but it has the advantage that there's a javascript-shell mode.

    Reed Sheridan, 24 June 2006

  10. kanat

    All links to Karl's page are broken as of today (Nov 15, 06). If you also can't access Karl's link, try the internet archive "Wayback Machine" page for it:

    http://web.archive.org/web/*/http://web.comhem.se/~u83406637/emacs/javascript.el

    There is a Mar 21 2006 entry (which states (C) 2005 in the file).

    kanat, 15 November 2006

  11. Reed, kanat: thanks for the links! I've updated the post.

    hober, 5 December 2006

  12. My page has moved from

    http://web.comhem.se/~u83406637/

    to

    http://web.comhem.se/~u34308910/

    Karl Landström, 23 December 2006

  13. Is it right that the string "\.js\’" should instead read "\.js$" in the line

    (add-to-list ‘auto-mode-alist ‘("\.js\’" . javascript-mode)))

    ?

    My comment won't be useful anymore if you update your code, so you can delete it.

    Jean-Baptiste Rouquier, 12 January 2007

  14. Jean-Baptiste: Sorry, WordPress was nuking some backslashes. Generally speaking, \\' is preferred to $ in `auto-mode-alist' forms — $ breaks with Sufficiently Weird filenames.

    hober, 16 January 2007

  15. RetroJ

    There is also a js-mode that is packaged with MozRepl. That said, I have yet to find a satisfactory mode for editing javascript, and I'm starting to believe that the world needs a truly good ecmascript-mode, built from the ground up, according to the spec. (unfortunately that name is taken) Once a good ecmascript-mode was completed, javascript-mode and actionscript-mode could be trivially derived from it. The universal lack of support for many perfectly valid javascript constructs, like anonymous objects, nested functions, functions as parameters to functions, &c., makes me wonder if deriving from cc-mode is a poor choice and the fatal flaw in all of the existing modes.

    RetroJ, 1 March 2007

  16. Some gresat examples, thanks

    Cardiff, 31 July 2007

  17. I think I'm using your color-theme... Very nice.

    I tried out Karl Landström’s javascript.el and it is very nice, but one bug that annoyed me to no end was the lack of word-boundary acknowledgment in the keyword regular expressions. This meant that words like "input" and "undo" were -partially- hilited, and it also affected the indenting of my "initialize" methods (a result of js-indent-operator-re not looking at word boundaries.) I fixed this by affixing word-boundary sequences to both ends of the strings returned by the calls to regexp-opt.

    I.e., wherever there is a

    (regexp-opt '(STRINGS) 'words)
    

    in the code, update it to

    (concat "\\b" (regexp-opt '(STRINGS) 'words) "\\b")
    

    Good stuff.

    Bendoh, 29 August 2007

  18. Did you send Karl a patch, Bendoh? I bet he'd gladly apply it.

    Edward O'Connor, 29 August 2007

  19. Gotcha. Sent it.

    Bendoh, 29 August 2007

  20. It seems that I jumped the gun:

    this problem is addressed in http://web.comhem.se/~u34308910/emacs.html

    Silly me.

    Bendoh, 29 August 2007

  21. Hunter

    Has anybody noticed a problem with regular expressions in javascript.el where ' and " aren't treated properly? For instance:

    var foo = /[a-zA-Z']+/.test("some'string");

    The ' in the regular expression starts javascript.el thinking there is an unterminated string constant.

    I'm still learning elisp, and I haven't been able to figure this one out.

    Hunter, 6 November 2007

  22. Looks like Karl's page disappeared again. :( Anyone have a current mirror? We should just put this thing up in Google Code or Sourceforge and let everyone hack on it...

    Ben Lowery, 14 November 2007

  23. It would be nice if there was a javascript+HTML mode, so that code fragments inside [HTML_REMOVED]lt;script[HTML_REMOVED]gt; tags would be easier to edit.

    brandon, 15 November 2007

  24. Ben Stock

    The current version of javascript.el can be found here.

    It also seems there is a modified version with (apparently) better handling of regex expression highlighting here.

    Ben Stock, 22 December 2007

  25. Thanks Ben! I've updated the post to reflect the new URL.

    Edward O'Connor, 31 December 2007

  26. Can't believe noone has posted a link to this yet, but Steve Yegge went and wrote a mega-super-awesome js2-mode a few months ago, complete with a non-heuristic recursive parser ported from Rhino. Sweeet! Find it here: <http://code.google.com/p/js2-mode/>

    Alex Yule, 29 July 2008

  27. Thanks for pointing that out, Alex. I've been planning to update this post for months, but hadn't gotten around to it.

    Edward O'Connor, 1 August 2008

  28. Matthew Flaschen

    This is a bit late, but why not:

    (cond ((locate-library "javascript")
              (autoload 'javascript-mode "javascript" nil t)
              (add-to-list 'auto-mode-alist '("\.js\'" . javascript-mode)))
             ((locate-library "generic-x")
              (require 'generic-x)))

    That way, there is no need to unconditionally load generic-x

    Matthew Flaschen, 9 March 2009

  29. Matthew,

    But generic-x contains many other goodies! I recommend everyone load it.

    Edward O'Connor, 8 April 2009

Add a comment

Posting...