Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Emacs JS mode for npm style

Is there a JS mode for emacs which is pretty much compatible with npm style?

So far I'm working with a modification of js2-mode with native intending features overridden and replaced with 'tab key = 2 spaces'. But it would be nice to have my editor be able to handle indenting like this:

var o = { foo : 'bar'
        , baz : 'foo'
        }
  , p
  , q = new Squash( o
                  , { start: 0
                    , limit: 50
                    }
                  )

As it is, js2-mode tries its best to indent correctly and cycles between possible positions, but for example 'comma lined up under r' isn't one of the options. Of course, writing decent indenting code in emacs is hard and my elisp isn't up to snuff there.

Note that if someone knows another editor that would work better for this, I could be open to switching.

like image 511
Tamzin Blake Avatar asked May 26 '11 20:05

Tamzin Blake


3 Answers

With much thanks to Cheeso's suggestion, here is a somewhat hacked-together mode-combo that handles indenting for comma-first or comma-last styles in the espresso way while using the great parsing and error-checking of js2-mode: https://github.com/thomblake/js-mode

If any problems are encountered, feel free to file bug reports - I intend to fix them.

EDIT: now found at https://github.com/thomblake/js3-mode and called js3-mode

like image 60
Tamzin Blake Avatar answered Nov 10 '22 01:11

Tamzin Blake


You should have a look at the improved js2-mode fork, it seems to be able to handle indentation a bit better than the ordinary modes.

like image 30
monotux Avatar answered Nov 10 '22 01:11

monotux


Emacs 23.2 includes js-mode, which is a renamed and touched-up Espresso. I just did "indent-region" on your redunkulous code and got this:

var o = { foo : 'bar'
          , baz : 'foo'
        }
, p
, q = new Squash( o
                  , { start: 0
                      , limit: 50
                    }
                )

I guess that's not exactly what you want. The commas are offset differently than you probably like.

(Gosh that's ugly.)


EDIT
Ok I looked into js-mode and the indentation seems to be done by js--proper-indentation. It looks at the current line and then tries to make decisions about how to indent.

It's got a bunch of conditions it tests, for various syntax patterns. I just put in a check for a line starting with a comma, and got these results:

var o = { foo : 'bar'
        , baz : 'foo'
        }
  , p
  , q = new Squash( o
                  , { start: 0
                    , limit: 50
                    }
                  )

I think that is what you want, but it still looks totally broken to me. Anyway this is how I did it.

Inject this cond into the top of the list for js--proper-indentation:

(defun js--proper-indentation (parse-status)
  "Return the proper indentation for the current line."
  (save-excursion
    (back-to-indentation)
    (cond
          ((looking-at ",")
           (let ((spos
                  (save-excursion
                    (while (looking-back "}[\t\n ]*")
                      (backward-sexp)
                      (if (looking-back ",[\t\n ]*")
                          (re-search-backward ",[\t\n ]*")))

                    (cond
                     ((looking-back "\\(,\\|(\\)[ \t]*\\<\\([^:=\n\t ]+\\)[ \t\n]*")
                      (re-search-backward "\\(,\\|(\\)[ \t]*\\<\\([^:=\n\t ]+\\)[ \t\n]*" (point-min) t)
                      (+ (current-column) 2))

                     ((re-search-backward "\\<\\([^:=\n\t ]+\\)[ \t]*\\(:\\|=\\)" (point-min) t)
                      (current-column))
                     (t 
                      nil)))))
             (if spos
                 (- spos 2)
               (+ js-indent-level js-expr-indent-offset))))
         ....

Be sure to keep the rest of the conditions in that defun - I don't know what they do but the're probably important.

No idea if this is robust, I haven't tested it except for your one test case. But this oughta get you started.

like image 41
Cheeso Avatar answered Nov 10 '22 01:11

Cheeso