inferior JavaScript mode を発見した。

Rubyirbと同じ使い勝手でRhinoをあれこれ試せないかとネットを探しまわっていた所、emacs inferior mode for JavaScripthttp://bryan-kyle.blogspot.com/2008/07/inf-jsel.htmlで発見した。
これまさに、期待していた通りの動作をしてくれる。それもそのはず、ruby の inferior ruby mode をそのままハックしたlispモジュールなのだ。

これを動作させるためには、事前にjs2-modeのインストールが必要。
js2-modeに関しては、今日たまたま上のエントリーで参照したEmacsでJavaScriptソースを快適に読むために:js2-modeとエグズーベラントCtags - 檜山正幸のキマイラ飼育記 (はてなBlog)が詳しい。

inferior JavaScript mode のインストール方法は、Bryan Kyle氏のブログのページ一番下 "download inf-js.el" から github へ飛んで、inf-js.el をload-pathの通った場所へダウンロード。
そして、以下を.emacsファイルに記述する。

(autoload 'run-js "inf-js" nil t)
(autoload 'inf-js-keys "inf-js" nil)
(add-hook 'js2-mode-hook
          '(lambda ()
             (inf-js-keys)))

これで、M-x run-js で inferior JavaScript mode を実行する事が出来るようになる。
ブログには、Rhino だけでなく、他のJavaScript処理系でも使えると書いてある。js-program-nameの値を書きかえると良いらしい。

ついでに、昔取った杵柄ではないが、ruby-modeが使いにくいので改造(その2) - From a Far East Island で inferior ruby mode の使い勝手を、自分の手に会うように機能追加するlispを書いた事が有る。これをそのまま inferior JavaScript mode でも使えるようにlispを書き変えてみた。

 ;; inferior javascript mode customize
(defun js-send-exp ()
  "Send a line to the inferior javascript process.
Cursol must be at the end of the line of the oneliner"
  (interactive)
  (let *1

(defun scroll-down-ijs ()
  (interactive)
  (setq curbuf (current-buffer))
  (if (get-buffer js-buffer)
      (pop-to-buffer js-buffer)
      (error "No current process buffer. See variable js-buffer."))
  (end-of-buffer)
  (pop-to-buffer curbuf))

(add-hook 'js2-mode-hook
	  '(lambda ()
	     (define-key js2-mode-map "\C-x\C-e" 'js-send-exp)))

要点は以下の3つ。

  • lisp inetractino mode のように、C-x C-e で、ワンライナーも関数定義もどちらも評価できる
  • 評価後、inferior JavaScript buffer を一番下までスクロールダウンして、評価結果が画面内に残るようにした後、もとの編集中のjavascript buffer にフォーカスを戻す
  • inferior JavaScript buffer が表示されていない状態でもJavaScript の評価を行うと同時に、inferior JavaScript buffer を表示し、評価結果を見れるようにする。

関数を評価したいときは、関数定義の最後の '}' の後で、ワンライナーを評価したいときは、行末の';' の後で、C-x C-e とすると評価できる。
ワンライナーの先頭と、関数定義の開始位置の特定には、js2-mode の関数 js2-beginning-of-defun を使用しているので、JavaScript の buffer の任意の場所で、

M-x   js2-beginning-of-defun

とする事で、評価範囲を調べる事が出来る。評価範囲は、js2-beginning-of-defun で移動した場所から、カーソル位置まで評価するようにしてある。(ので、関数の途中でC-x C-e とすると、inferior JavaScript buffer が '}' 待ちの状態になってしまう。)

*1:beginning (save-excursion (js2-beginning-of-defun) (point)))) (js-send-region beginning (point))) (scroll-down-ijs