コメントや文字列中で勝手にyasnippetが展開されてうざい件→解決

yasnippet.elはデフォルトでコメントや文字列中では勝手に展開されないような設定になっている…はずだった。

(defvar yas/buffer-local-condition 
  '(if (and (not (bobp))
	    (or (equal "font-lock-comment-face"
		       (get-char-property (1- (point))
					  'face))
		(equal "font-lock-string-face"
		       (get-char-property (1- (point))
					  'face))))
       '(require-snippet-condition . force-in-comment)
     t))

デフォルトでうまくいくはずなのだが、俺の環境(Emacs22)だとget-char-propertyはsymbolを返すのでうまくいかない。

しかも、このコードget-char-propertyを二回も呼んでるからまずい。シンボルのどれかに一致するか検査するならmemq使おうよ。

(setq yas/buffer-local-condition
      '(or (not (memq (get-char-property (point) 'face)
                      '(font-lock-comment-face font-lock-string-face)))
           '(require-snippet-condition . force-in-comment)))

しかし、これでもだめ。というのは、俺はhlline-modeをonにしているため、 (get-char-property (point) 'face) がhlline-faceを返してしまうからだ。そうなるとコメントや文字列中に勝手にyasnippetが展開されててマズーとなる。

そこで M-x find-function get-char-property でソースを追ってみることにする。似たような関数を探すためだ。似たような関数はたいていソースの近くに書いてあるからだ。
get-char-propertyの兄弟でget-text-propertyを見付けた。こいつらの違いは、get-char-propertyはoverlayまでチェックすること。hlline-faceはoverlayによるものなので、get-text-propertyを使えばよいことがわかった。

最終的な設定はこうなった。ついでにfont-lock-doc-faceも入れておいた。

(setq yas/buffer-local-condition
      '(or (not (memq (get-text-property (point) 'face)
                      '(font-lock-comment-face font-lock-doc-face font-lock-string-face)))
           '(require-snippet-condition . force-in-comment)))

yasnippetは便利な反面、勝手に展開されたときのストレスはハンパじゃない。ましてや、スペースをtriggerにしているからなおさら。スペースじゃないとsnippetが展開されていること自体を忘れてしまう。

同じ悩みを持っている人は、↑の設定を試してみよう!