最近の変更サイトマップ

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 "

EmacsのM-x compileで自動的にMakefileを探し出すようにする

Emacs上でソースコードのコンパイルを行うにはM-x compileコマンドを使う。するとmakeが走り、結果がCompilatinバッファに表示され、M-x next-errorなどでエラー行に一発ジャンプ出来て超便利ッ……という所までは良く語られる。が、しかーし、肝心のMakefileの指定方法に触れている解説が少ない。

実際のところ、M-x compileのmakeの引数指定のところで書いてやればいいのだが、カレントパスや取り掛かっているプロジェクトごとにアレコレ考えてMakefileを指定するのは現実的ではない。それする位なら、Compilationの利点を捨て、ターミナルのコマンドヒストリーでコンパイルした方がよっぽどマシである。たいてい、Makefileはソースフォルダのトップなりに置くので、編集中のファイルから上に辿り、見つかったMakefileでmakeしてくれれば済む話。

で、ようやくそれを実現する方法を見つけた。Recursively go up to find Makefile and compileに載ってるelispを使う。万が一消えた時用に転載。

(defun desperately-compile ()
  "Traveling up the path, find a Makefile and `compile'."
  (interactive)
  (when (locate-dominating-file default-directory "Makefile")
  (with-temp-buffer
    (cd (locate-dominating-file default-directory "Makefile"))
    (compile "make -k"))))
 
; C-x mでMakefileを探してコンパイル
(global-set-key (kbd "C-x m") 'desperately-compile)

上記サイトの回答に書いてあることだが、指定ファイルが見つかるまでディレクトリを遡って検索する打って付けのlocate-dominating-fileなる関数があるそうで。今回の用途だけではなく、様々な場面で役に立ちそう。

EmacsのCompletionsバッファを新規ウィンドウではなく既存ウィンドウに表示させる

通常、EmacsでTAB補完の時とかに表示されるCompletionsバッファは、フレーム1)下部を分割した一時的なウィンドウ2)として表示される。言葉じゃわかりにくいので、スクショを張っとくと↓こんな感じね。 こっちは嫌(Completionsウィンドウが独立に開く)

自分のEmacsの使い方は垂直分割した2つのウィンドウ表示が基本で、Completionsバッファは非アクティブな方のウィンドウに出て欲しい。その方が補完候補の一覧性が圧倒的だし、ウィンドウがパカパカしないのがいい。スクショを張(ry こっちがいい(Completionsバッファが非アクティブなウィンドウに表示される)

ここの回答に載ってるelispを参考に、ウィンドウが1つの時はウィンドウ幅に応じて分割方向を変えるようにしてみた。

(defun display-on-side (buffer &optional not-this-window frame)
  (let* ((window (or (minibuffer-selected-window)
                     (selected-window)))
         (display-buffer-function nil)
         (pop-up-windows nil))
    (with-selected-window (or window (error "display-on-side"))
      (when (one-window-p t)
        (if (> (window-pixel-width) (window-pixel-height))
            (split-window-horizontally)
          (split-window-vertically))
        )
      (display-buffer buffer not-this-window frame))))
(setq display-buffer-function 'display-on-side)

水平2分割した状態で使うと、非アクティブなウィンドウの方がCompletions表示時に勝手にリサイズされる問題があったりする…。自分は水平分割使わないので放置してます、すいません。えらいひと直して教えてください。

参考サイト

1) Emacs用語としてのフレーム
2) Emacs用語としてのウィンドウ

Emacsでシンボリックリンクをそのままのパスで開く

/hoge/piyo/symlink/path/to/realというディレクトリのシンボリックリンクがあったとして、Emacsで/hoge/piyo/symlink/src.cppを開くと、自動で実体のパス/path/to/real/src.cppに読み替えて開いてくださりやがる。大抵のケースでこれが望まれる挙動なんだろう。

だがしかし、バージョン管理システムが絡んでくると話は変わる。

VCS下のファイルand/orフォルダの一部を別の場所に置いてシンボリックリンクで繋いでるような場合、バージョン管理がうまく機能しなってしまう(そんな運用すんなよっていうツッコミはナシで)。/hoge/piyo/がVCS下なら、/hoge/piyo/symlink/src.cppはそのままのパスとして扱いたいワケ。

そんな時は次のようにすればOK!

(setq-default find-file-visit-truename nil)

これでシンボリックリンクを手繰らずに、与えられたパスそのままにfind-fileしてくれるようになる。

EmacsでBOM付きUTF-8を扱うときはutf-8-autoを使おう

BOM付きUTF-8文章のファイルローカル変数(ファイル先頭の-*-で囲まれたアレ)のcodingutf-8-autoとしておくのが良さそう。autoだとBOMの有無を自動判別し、よしなに扱ってくれる。

大抵はutf-8(強制BOMなし)かutf-8-with-signature(強制BOMあり)のどちらかで事足りるが、Emacsと別のアプリ間で同一ファイルを行き来させると、たまにBOMの処理がバッティングしてBOMが2個ついたり消えたりって事が起きるので……。まぁ、Perforceの事なんですけどね!

PerfoceにBOM付きUTF-8のファイルを登録すると、どうもチェックアウト時にBOMを付加してるようで、それがEmacsのutf-8-with-signature処理と被って二重BOMになるのよね(´・ω・`)。かといって、ただのutf-8にすると何かの拍子にBOMが消えてしまい色々不都合なのよね(必ずしも消える訳でもないのがそれはそれで謎)。

BOM付きUTF-8とかこの世から死滅すればいいのに。ゲイツ、てめーの事だ!!BOM付きUTF-8は、CJK統合漢字の次に嫌いなUnicodeのクソ仕様だと思うわ。大体だね、16bitに全ての文字を収めようとしたUnicode自体がアルファベット圏人の浅はかな考えに起因するクソ規格であって、CJK統合漢字などという「見た目が同じだから」とかいう非漢字圏人の安易な発想に基づく仕様は、漢字圏各国の文化を破壊する人種差別的行為であると言わざるを得ないものであり(以下略

start.txt · 最終更新: 2016-05-07 17:46 by decomo
CC Attribution-Noncommercial-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0