js2-modeでClosure Libraryのコーディング規約に沿わせる

| 【4分で読めるよ!】 | コメント(0) | トラックバック(0)

 最近仕事ではJavaScriptを書いてます。JSのフレームワークにはjQueryなどいくつかありますが、アリエルではGoogle Closure Libraryを使っています。個人的には好きなフレームワークです。prototypeを勝手にいじくりまわさない辺りはお行儀がよろしいと思います。

Google JavaScript Style

 Closure Libraryには以下のようなコーディング規約があります。同じメソッド定義でも、JSではいろんな書き方ができるので、こういう規約には従っておいたほうがいいです。

 僕はEmacsでJavaScriptを書くときはjs2-modeを使っています。しかし、既に周知のように、js2-modeのインデントはクソです。特にgoog.array.forEachなどにfunctionを渡すときのインデントは発狂ものです。

// × js2-mode
goog.array.forEach(coll, function(elem) {
                           // ここに自動インデント
                         });

// ○ Google JavaScript Style
goog.array.forEach(coll, function(elem) {
  // ここにインデントしたい
});

espresso-modeのインデントを使う

 そこでインデントだけespresso-modeのインデントを使います。espresso-modeは以下のサイトからダウンロードしてください。

(autoload 'js2-mode "js2" nil t)
(add-hook 'js2-mode-hook
          #'(lambda ()
              (require 'espresso)
              (setq espresso-indent-level 2
                    espresso-expr-indent-offset 2
                    indent-tabs-mode nil)
              (set (make-local-variable 'indent-line-function) 'espresso-indent-line)))

 espresso-modeのインデントは割と素直なので、ほとんど困ることはありません。

case文のインデントを修正

 ただし、これでもswitch文のcaseラベルのインデントが規約に沿いません。

var Fruit = some.long.namespace.Fruit;

// × caseが文頭に並んでしまう
switch (fruit) {
case Fruit.APPLE:
  ...
case Fruit.BANANA:
  ...
})

// ○ 規約では他と同じ2つのインデント
switch (fruit) {
  case Fruit.APPLE:
    ...
  case Fruit.BANANA:
    ...
})

 そこで自前でインデント関数を書いて、case文のときだけインデントを変えるようにします。

(autoload 'js2-mode "js2" nil t)
(add-hook 'js2-mode-hook
          #'(lambda ()
              (require 'espresso)
              (setq espresso-indent-level 2
                    espresso-expr-indent-offset 2
                    indent-tabs-mode nil)
              (defun my-js-indent-line ()
                (interactive)
                (let* ((parse-status (save-excursion (syntax-ppss (point-at-bol))))
                       (offset (- (current-column) (current-indentation)))
                       (indentation (espresso--proper-indentation parse-status)))
                  (back-to-indentation)
                  (if (looking-at "case\\s-")
                      (indent-line-to (+ indentation 2))
                      (espresso-indent-line))
                  (when (> offset 0) (forward-char offset))))
              (set (make-local-variable 'indent-line-function) 'my-js-indent-line)))

まとめ

 これで大体Closure Libraryの規約と同じです。実はあと1個だけちゃんとインデントできないところがあるのですが、対応が面倒そうなので秘密にしておきます。最初に見つけた人にはペロペロキャンディをあげる。

参考サイト

トラックバック(0)

トラックバックURL: http://e-arrows.sakura.ne.jp/mt/mt-tb.cgi/175

コメントする

このブログ記事について このアーカイブについて

このページは、深町英太郎が2010年12月 8日 11:14に書いたブログ記事です。

ひとつ前のブログ記事は「Shibuya.lispで「Lispで仕事をするために」というLTをしました」です。

次のブログ記事は「anything-ari.elを作りました」です。

Ariel Labs
Name:深町英太郎
Age:23歳
Living:京都府
Company:はてな
Hatena Id:id:nitro_idiot
Facebook:eitarow.fukamachi
mixi:ID:6756132
Twitter:nitro_idiot
GitHub:fukamachi
LinkedIn:eitarowfukamachi

Techonrati

Technorati search

» リンクしているブログ

Powered by Movable Type 4.23-ja