[emacs] jit-lock-mode なのに、ファイル読み込み時に何故かバッファ全てがfontifyされてしまう → 解決

font-lock-support-mode で jit-lock-mode に設定しているにもかかわらず、何故かファイル読み込み時にバッファ全てが fontify されてしまう。
そのため、ファイル読み込みにもの凄く時間がかかってしまい、いつもイライラしていた。
随分と長い間放置していたのだが、ついに我慢出来なくなり重い腰を持ち上げて調査することに。


まず、fontify がなされている機序だが、ファイル読み込みが終了した後、font-lock-fontify-bufferがコールされ、font-lock-fontify-buffer-function に定義されている font-lock-default-fontify-buffer が連鎖して呼ばれることでバッファ全てが fontify されている。


ところで、一度ファイルを読み込んだ後に手動で (font-lock-fontify-buffer) を行うと、一瞬で動作を終えてしまう。
きちんとjit-lock-modeでのfontifyになっているようだ。


デバッガで調べてみると、手動で (font-lock-fontify-buffer) をコールしたときには、 font-lock-fontify-buffer-function が jit-lock-refontify に変わっている。


ということは、初回読み込み時に font-lock-fontify-buffer-function が jit-lock-refontify になっていれば良い訳なので、

(setq-default font-lock-fontify-buffer-function 'jit-lock-refontify)

.emacs に記述することで解決。


しかし、何故 font-lock-fontify-buffer-function の設定がおかしいのか気になるので、もう少し調べてみた
ロード終了後のコールスタックは↓こんな感じになっていて、font-lock-mode-internal が fontify-bufferよりも後にコールされている。
linkd-mode -> linkd-enable -> font-lock-fontify-buffer -> .... -> font-lock-mode-internal

どうやら、font-lock-fontify-buffer は、font-lock-mode であろうが無かろうが、実行出来ることを保証しているようです。
シラナカッタ


もしくは、find-file-hook 辺りの設定の順番がおかしいのかな……


2009/10/21 追記
c++-modeで font-lock-mode が on になるタイミングは、after-change-major-mode-hook で global-font-lock-mode-enable-in-buffer()がコールされた後。
しかし、linkd は、c-mode-common-hook / c++-mode-hook で font-lock-fotify-buffer() をコールしている。
このため、linkd が fontifyするときには、まだfont-lock-modeの初期化が終わっておらず、デフォルト値のlazy-modeでfontifyされてしまうのが原因。

以前の対策

(setq-default font-lock-fontify-buffer-function 'jit-lock-refontify)

だけでは初期化が足りないような気がするので、

(defadvice linkd-enable (before turn-on-font-lock-mode-before-linkd-enable activate)
  (turn-on-font-lock))
(defadvice linkd-disable (before turn-on-font-lock-mode-before-linkd-disable activate)
  (turn-on-font-lock))

にしてみた。
本当は、font-lock-fontify-buffer()に対してadviceした方が良いのか?! むむぅ。。


c++-modeのafter-change-major-mode-hookで font-lock-mode が onになる時のバックトレースは下記の通り


font-lock-mode-internal(t)
font-lock-default-function(t)
font-lock-mode()
turn-on-font-lock()
turn-on-font-lock-if-desired()
global-font-lock-mode-enable-in-buffers()


2009/10/23 追記
やはり、根本の font-lock-fontify-buffer の方に adviceするようにした。

(defadvice font-lock-fontify-buffer (around cancel-font-lock-fontify-buffer-unless-font-lock-mode activate)
  (if font-lock-mode
      ad-do-it))

Googleで調べてみても同じような症状の人は見あたらないので、もしかしたら他の箇所で何かヤッチマッテルのかもしれない。。