ツールチップで C プリプロセッサマクロの定義内容を表示

昨日のエントリで、リモートデバッグの際には `gud-tooltip-mode' は無効にしておいた方が良いと書きました。
私の場合、マウスを殆んど使わない (Emacs を使ってる人は殆どそうだと思うのですが、最近だと違ったりしますかね) ので、ツールチップを有効にしていても余り良いことはなく、無効にしていても影響が無いというのはあるのでしょう。

しかし、GDB を `gdb-many-window' で使っていると、ローカル変数の表示バッファ (*locals of BUFFER-NAME*) などに表示されているのが便利で、gdb バッファで `print var' なんてやらなくなってきます。
しかし、`gdb-many-window' でブレークポイントやコールスタックなどバッファも同時に表示していると、それぞれのウィンドウサイズを余り大きく取れず、ローカル変数が少し多いとウィンドウからはみ出てしまってスクロールしないと見られない状態になってしまいます。そうすると、ツールチップで簡単に見られるのが結構有効に思えて来ました。

で、`gud-tooltip-mode' を有効にして利用しようとすると、gdb-ui の `gdb-create-define-alist' で `call-process' を使ってるので、リモート環境のデバッグの場合は、動作しない様になってました。
なのでこれを `process-file' に置き換えます。
`start-process' は `start-file-process' で、`call-process' は `process-file' で置き換えてやるのが、Magic File Names を利用するために simple.el が用意してくれているスキームですね。こうしておけば、適切な `find-file-name-handler' が設定されていれば、良きに図らってくれます。
GDB と同じ位に便利な flymake が `start-process' を使っているので、`start-file-process' に置き換えるって話は、随分前に Emacs Tramp + flymake - higepon blogid:higepon さんが、紹介されていましたね。

ここで、`call-process' で取ってきてるのは、C プリプロセッサの `#define' で定義されたマクロの値ですね。`gcc -E -dM -' とかして、#define されたシンボルとその値を収集して `gdb-define-alist' に保持しています。そして、この値には、マクロ定義の定義内容自体も含まれます。これで、プリプロセッサで定義したシンボルにマウスカーソルを合わせると、定義された値やマクロ定義の内容がツールチップで表示されるという訳です。

ところがこの `gdb-define-alist' の値を表示する挙動なんですが、これが私にはちょっと良く判らない動作をします。リモート環境とかは関係なく、GDB のプロセスが生きているときは見ないんですよね、`gdb-define-alist' のことを。
GDB のプロセスが生きてるときは、必ず `print SYMBOL' なんてコマンドを GDB に送って値を問い合わせています。しかし、プリプロセッサマクロの場合だと、そもそも GDBプリプロセッサでの定義内容のことは知りもしないので、そんなシンボルはスコープにねえ、って素気無いツールチップが表示されることになってしまいます。
折角取ってきてるんだから使えば良いのにと思いますが、実際のところ、プリプロセッサで定義されたシンボルなのか、変数としてのシンボルなのかは判断する術はないので GDB に問い合わせることにしたんでしょうかね。

私としては、プリプロセッサの定義値を見るのに、find-tag する手間を省けた方が嬉しいので、

;; ちょっと無理矢理だが、`gud-tooltip-tips' の実行時には、最初に必ず
;; `gdb-define-alist' から assoc し、存在していればそれを `tooltip-show' し、
;; 無かったときのみ本来の `gud-tooltip-tips' を実行する様にアドバイス。
(defadvice gud-tooltip-tips (around ad-gud-tooltip-tips activate)
  (or (let *1
              expr))))
      ad-do-it))

などとして、無理矢理見れる様にしています。先にも書きましたが、ローカルでのデバッグでも同じですので、常に上記の設定を有効にしています。

まあ、ツールチップに関しては、リモートの場合に遅過ぎでもたるし、下手をすると詰まるようなので、通常は `gud-tooltip-mode' を無効にしておき、必要なときだけ有効にして利用していますが。

*1:expr (tooltip-expr-to-print event))) (with-current-buffer (tooltip-event-buffer event) (let ((define-elt (assoc expr gdb-define-alist))) (unless (null define-elt) (tooltip-show (cdr define-elt) (or gud-tooltip-echo-area tooltip-use-echo-area