LoginSignup
9
7

More than 5 years have passed since last update.

Flycheckでnode_modules/.binを使う

Last updated at Posted at 2016-10-29

動機

FlycheckESLintを使っていると、グローバルインストールされた eslint コマンドではなく、各プロジェクトにインストールされた node_modules/.bin/eslint を使いたくなるときがあります。

実現

npm bin コマンドの出力を exec-path に追加することで実現します(npm bin コマンドは普通、そのプロジェクトの node_modules/.bin の絶対パスを出力します)。
下記のEmacs Lispコードを init.el に追加してください。

init.el
(defun my/use-node-modules-bin ()
  (let* ((local-path (replace-regexp-in-string
                      "[\r\n]+$" "" (shell-command-to-string "npm bin"))))
    (setq-local exec-path (cons local-path exec-path))))

(add-hook 'flycheck-mode-hook #'my/use-node-modules-bin)

別解(2017-10-25 追記)

add-node-modules-path という素晴らしいパッケージを見つけましたので、これを使いましょう。
exec-path をバッファローカルに変更してくれます。

これでもう flycheck-executable-find をカスタマイズする必要はありません。

別解(2017-07-21 追記)

  • npm bin は Node.js プロセスを立ち上げるので遅い ⇒ node_modules 固定で Emacs Lisp で実装する
  • exec-path を更新するのではなく、Flycheck が提供する flycheck-executable-find 変数を使う
init.el
(defun my/find-npm-command (command)
  (let* ((dirname "node_modules")
          (root (locate-dominating-file default-directory dirname)))
    (if root (concat
               (file-name-as-directory root)
               (file-name-as-directory dirname)
               (file-name-as-directory ".bin")
               command))))

(defun my/executable-find (command)
  (let* ((file-path (my/find-npm-command command)))
    (if (and file-path (file-executable-p file-path))
      file-path (executable-find command))))

(setq flycheck-executable-find #'my/executable-find)

最終解(2017-07-22 追記) ⇒最終解ではないです :bow:

これが一番シンプルな解(かも)。

このQiitaの記事にあるように、あらかじめ PATH を設定しておいて、

export PATH="./node_modules/.bin:${PATH}"

# Or
pathmunge ./node_modules/.bin

exec-path-from-shellを使って PATH を Emacs に読み込ませるようにすればよいです。

こうすることで、上記にあるような Flycheck への設定はすべて不要になります。

セキュリティ上問題あり(2017-07-24 追記)

…と書きましたが、

export PATH="./node_modules/.bin:${PATH}"

は、

export PATH="${PATH}:./node_modules/.bin"

とするのが、セキュリティ上正しいです。

理由は、仮に ./node_modules/.bin/touch というファイルが存在した場合、OSコマンドの touch をオーバーライドして悪意のあるコマンドを実行することができるからです。
(詳しくは :point_right: https://github.com/npm/npm/issues/957#issuecomment-237064313

ただ PATH の一番最後に ./node_modules/.bin を置いてしまうと、グローバルインストールした npm パッケージの方がローカルインストールしたパッケージより優先されてしまうという点が悩ましいです。 :sob:

やはり Flycheck に設定した方が、影響範囲が限定されるので安全かもしれません。

9
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7