simple-hatena-modeで小見出し --adviceは便利--

問題

ブログの投稿は、基本的に simple-hatena-mode を利用させてもらっている。このモードでは、行頭で * を入力すると、自動的にタイムスタンプを挿入してくれる。これは便利なんだけど、小見出しを使いたい時には不便(はてな記法では、行頭で**とアスタリスクが2つ続くと小見出しと認識してくれるんだけど、simple-hatena-mode をそのまま使っている場合、1つ目の*を打つとタイムスタンプが挿入されて*1301401916*というような感じになる。で、2つ目の*を打つと、*1301401916**となって、タイムスタンプを消さないといけない)。
で、こういう時は、emacs lispの advice という機能を使おうという話。

adviceとは

emacs lispには、adviceという便利な機能があって、次のようなことが出来る。

  • 特定の関数の実行前に、特定の動作をする(before advice)
  • 特定の関数の実行後に、特定の動作をする(after advice)
  • 特定の関数の実行が、常に特定の環境で為されるようにする(around advice)

これは、既存の関数の定義を変えることなく、その振る舞いを変更したい場合に威力を発揮する。
続きに、コード例と応用例。

コード例

>> (defun hoge () data-directory)
hoge

>> (hoge) ; デフォルトの data-directory の値
"/Applications/Emacs.app/Contents/Resources/etc/"

>> (defadvice hoge (around hoge-advice activate)
>>   (let ((data-directory "hoge")) ad-do-it)) ; hoge 関数の実行は、 data-directory 変数が "hoge" に束縛されている環境で為される
hoge

>> (hoge)
"hoge"

>> (ad-deactivate 'hoge) ; advice を無効化
hoge

>> (hoge)
"/Applications/Emacs.app/Contents/Resources/etc/"

応用例

で、今回の問題は、次のような adviceを書けば解決する。

(defadvice simple-hatena-electric-asterisk
  (after simple-hatena-electric-asterisk-advice activate)
  "When the second * is inputted on the head of a line, 
remove time stamp which was inserted by the function"
  (let
      ((pos (line-beginning-position)))
    (if (and
	 simple-hatena-use-timestamp-permalink-flag
	 (= (current-column) 13)
	 (string-match "\\*[0-9]+\\*\\*"
		       (buffer-substring pos (+ pos 13))))
	(delete-region pos (+ pos 11)))))