EmacsでTernのサードパーティ製プラグインを使おうとしたら Cannot find module と怒られた
Ternが補完できるオブジェクト
最近、Ternを使い始めて、 EmacsでJavascriptのコーディングがすこぶる快適になりつつあります。
ただ、Ternがデフォルトで補完できる型は、
組み込みオブジェクト以外では一部のライブラリ(jQueryとか)のオブジェクトに限られ、
それ以外の型を補完できるようにするには、型情報をTernに知らせる必要があるようです。(※)
※ 英語に自信ないので間違ってるかも
Google Maps API の型情報を提供してくれるプラグイン
で。最近、 Google Maps API を使ってコーディングした時、
そのオブジェクトも補完できるようにしたいと思って調べたら、
Google Maps API の型情報を追加してくれるプラグインを見つけました。
https://github.com/angelozerr/tern.googleapi
Ternにプラグインを認識させる
プロジェクトルート(.tern-projectがあるフォルダ)に
プラグインファイル(今回は、上記リポジトリのplugin/gmaps_3.17.js)を置き、
.tern-projectに、以下のように記述すれば良いとのこと。
{ "plugins": { "gmaps_3.17": {} } }
プラグインがrequireしているモジュールが見つからない
これで補完できるのかなとウキウキしながら、コーディングを始めたら、
以下のように Cannot find module と怒られてしまいました...
Error: Cannot find module 'tern/lib/infer'
そもそも、JavascriptやNode.jsでの外部ファイルの読み込みの仕組み自体に無知でしたが、
調べてみると、NODE_PATHも正しく設定されているし、プラグインの記述も正しそうだとわかりました。
Ternのプロセスに環境変数が引き継がれてなかった
Emacsから生成されるTernのプロセスにNODE_PATHの値が引き継がれてなかったです。
GUIのEmacsでは有名な問題で、exec-path-from-shellを使って解決できます。
今回の場合、以下の設定を追加することで、
無事 Google Maps API のオブジェクトが補完できるようになりました。
(add-to-list 'exec-path-from-shell-variables "NODE_PATH")
ちなみに
Ternにプラグインとして認識させるには、
"tern-プラグイン名"というパッケージ名のnpmパッケージを作成することでも可能です。
今回みたいに、共通で使えるプラグインの場合、そっちの方がスマートじゃないかと。
以下の手順で、
該当のプラグインファイルだけのnpmパッケージをインストールして
Ternに認識させることができました。
/tmp$ mkdir gmaps_3.17 /tmp$ npm init This utility will walk you through creating a package.json file. It only covers the most common items, and tries to guess sane defaults. See `npm help json` for definitive documentation on these fields and exactly what they do. Use `npm install <pkg> --save` afterwards to install a package and save it as a dependency in the package.json file. Press ^C at any time to quit. name: (tmp) tern-gmaps_3.17 version: (0.0.0) description: entry point: (index.js) gmaps_3.17.js test command: git repository: keywords: author: license: (BSD) About to write to /tmp/package.json: { "name": "tern-gmaps_3.17", "version": "0.0.0", "description": "", "main": "gmaps_3.17.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "BSD" } Is this ok? (yes) /tmp$ mv package.json gmaps_3.17/ /tmp$ git clone https://github.com/angelozerr/tern.googleapi.git Cloning into 'tern.googleapi'... remote: Counting objects: 521, done. remote: Total 521 (delta 0), reused 0 (delta 0) Receiving objects: 100% (521/521), 1.00 MiB | 269 KiB/s, done. Resolving deltas: 100% (51/51), done. /tmp$ cp tern.googleapi/plugin/gmaps_3.17.js gmaps_3.17/ /tmp$ cd gmaps_3.17/ /tmp/gmaps_3.17$ npm install -g tern-gmaps_3.17@0.0.0 /home/hiroaki/.nvm/v0.10.15/lib/node_modules/tern-gmaps_3.17 /tmp/gmaps_3.17$