EmacsのTRAMPのrgrepでfind: paths must precede expression: ^^!^が出るようになった顛末
Windows 10 + PuTTY(plink) + Emacs 26.1な環境でLinuxターゲットのSSH TRAMPがいい感じに使えてたんだけど、PuTTYをmsys2のものに置き換えたら、rgrepが「find: paths must precede expression: ^^!^」なるエラーを吐いて使えなくなってしまった。これじゃ仕事にならん!ってなもんで前のPuTTYに戻したものの状況は変わらず…オワタ\(^o^)/
とりあえずemacs/share/emacs/26.1/lisp/progmodes/grep.el.gz
の1153行目付近、-prune -o
と(shell-quote-argument “!”)
から文字列を結合してるあたりを削り、M-x byte-compile-file grep.el.gz
して、超無理やり解決した。
同様の問題が起きた時の参考として、解決に至るまでの顛末をメモ。
- lgrepやgrep-findは動くのでrgrepの問題と判断。
- エラーメッセージと*grep*バッファのコマンドログから -prune -o ^“^!^” -type d あたりが怪しいと判断。実際、^“^!^”の先頭のサーカムフレックスは引数の文字としておかしくない?
- M-x describe-function rgrepでrgrep関数の定義を探す→grep.el.gzと判明
- ファイル内を「rgrep」をキーワードに流し読み。rgrep-default-command関数で実行するコマンドを組み立ててる予感!
- 一応scratchバッファで(rgrep-default-command “XXX” “YYY” “ZZZ”)を実行して結果を見てみる→あたり!
- rgrep-default-command関数の中で「!」を使ってるところを探す→(shell-quote-argument “!”)発見
- scratchバッファで評価してみる→変なエスケープのされ方をされている!
- 「!」は結合しない方向で、findの引数の関係が正しくなるように前後の処理を調整
- M-x byte-compile-file grep.el.gzしてEmacs再起動
- rgrepが使えるようになっていることを確認
根本原因はshell-quote-argument
の挙動が変わった(?)ことっぽいけど、なぜ変わったのかは不明のまま。PuTTYを差し替えたこと以外、何もいじってないはずなんだけどな…。
同様にshell-quote-argument
の実装を見てみても、OSによって処理を分岐させてるだけで変なところはない。……ん?待てよ、TRAMPの場合はOSはどういう扱いになるのこれ?ちゃんとリモート側のシステムにあわせてsystem-typeの中身が変わるのこれ…?
2018-12-04 追記
サーカムフレックスはコマンドプロンプトでのエスケープシーケンスらしいので、TRAMPしてるにもかかわらずshell-quote-argument
がWindows用の挙動を示すのが根本原因のようだ。
先の回避策では除外ディレクトリの指定が効かなくなってしまうので、grep.el.gzの1153行目あたりを以下のように変更した。
(and grep-find-ignored-files (concat (shell-quote-argument "!") " -type d "
↓
(and grep-find-ignored-files (concat " '!' -type d "