GNU global によるタグ検索を Emacs + helm から利用するための helm-gtags.el という拡張がある。これが TRAMP 環境だとうまく動かないので、自前で少しいじって使っている。
具体的には、外部コマンドの実行部分を call-process-shell-command
から shell-command
へ置き換えている。
例えばこんな感じ。
(call-process-shell-command "global -p" nil t)
(shell-command "global -p" t)
パッと見で分かるとおり、どちらも global
という外部コマンドを実行している。引数の指定により、どちらもコマンド実行結果をバッファに書き出すようになっている。
それであれば、わざわざ call-process-shell-command
を shell-command
へ書き換えなくとも良いのではないか?と思うところなのだが、この2つのコマンド、ファイルがローカルにあるか、リモートにあるかで挙動が変わる。
テスト用に次のような関数を作ってみた。uname -a
コマンドを実行するだけの簡単なもの。
(defun test-call-process-shell-command()
(interactive)
(call-process-shell-command "uname" nil t))
(defun test-shell-command()
(interactive)
(shell-command "uname" t))
まず、これらの関数をローカル(Mac OS X)の test.txt を読み込み、その中で M-x を使って実行してみる。
# test.txt in OS X Mavericks
# M-x test-call-process-shell-command
Darwin
# M-x test-shell-command
Darwin
どちらの関数の結果も Darwin が返ってきている。
次に TRAMP を使ってリモートサーバ(Debian wheezy)にある test.txt を読み込み、同じように実行してみる。
# test.txt in Debian wheezy
# M-x test-call-process-shell-command
Darwin
# M-x test-shell-command
Linux
test-shell-command
の実行結果が Linux となった。
test-shell-command
の実体は、shell-command
関数を実行しているだけだなので、つまりこれは「shell-command
の引数のコマンドがリモートサーバで実行された」ことを表している。
しかし、shell-command
がリモートサーバを考慮して実装されているのかと言うと、そうではない。本来の shell-command
関数は、call-process-shell-command
と同じように Emacs が稼働中のマシンでコマンド実行する作りになっていた。
じゃあ、なんでリモートサーバで外部コマンドが実行されたのが疑問だったのだが、結局のところ TRAMP が shell-command
を差し替えて実行していた。
tramp.el
内に tramp-handle-shell-command
関数があり、こいつが shell-command
と同等の処理をリモートサーバ上で実行する処理を行なっていた。
TRAMP そのものの挙動の理解が足りていないので、何をやっているのか分からない部分も多いのだけど、いろいろゴニョゴニョやって実現させているようだ。
つまり何が言いたいのかというと、helm-gtags
の call-process-shell-command
を shell-command
に変えてしまえば TRAMP にも優しくなるよと思うのだけど、その他の影響が存在するのかがいまひとつ把握しきれずに提案(pull request)が投げられなくてモヤモヤしている。
こんな感じでしょうか?<br>https://github.com/yewton/emacs-helm-gtags/commit/d626d0247d81a067ae661bad2c69045f2d1936b4<br><br>とりあえず pull request 出してみちゃおうかなと思ってます。。