hatena-mode で現在のエントリのリンクを作成する

過去の日記へのリンクが欲しいときにあったら便利かなと思い作ってみた。
キーバインドは C-c C-l が空いてたからそれにした。
hatena-mode でファイルを開いてる状態で、C-c C-l すると現在のエントリのリンク(はてな http 記法)を作り、それをキルリングに保存する。

(add-hook 'hatena-mode-hook
          '(lambda ()
             (define-key hatena-mode-map "\C-c\C-l" 'make-link-for-current-entry)))

(defun make-link-for-current-entry ()
  "現在のエントリのリンク(はてな http 記法)を作成し、キルリングに保存します。
保存されるリンクの例 [http://d.hatena.ne.jp/gan2/20080224/1203830553:title].

Make link (hatena-http-notation) for current entry,
for example [http://d.hatena.ne.jp/gan2/20080224/1203830553:title].
And save the link in the kill ring."
  (interactive)
  (save-excursion
    (let ((entry-id)
          (link))
      (forward-line)
      (if (re-search-backward "^\\*\\([0-9]+\\)\\*" nil t)
          (progn (setq entry-id (buffer-substring-no-properties (match-beginning 1) (match-end 1)))
                 (setq link (concat "[http://d.hatena.ne.jp/" hatena-usrid "/"
                                    (buffer-name) "/" entry-id ":title]"))
                 (message "Make link: %s" link)
                 (kill-new (concat link "\n")))
        (message "Error. Cannot make link.")))))

英語でドキュメント書いてみたけど自信なし。
キルリングに保存する関数っていうのはあんまり行儀がよくないのかもしれない。
その辺はよく分からない。
moccur-grep-find と組み合わせるとなかなか便利。
僕的作業フローはこう。

  • Ruby に関するエントリを書いている
  • 過去に似たようなこと書いてるか調べたくなる
  • 「moccur-grep-find ~/.hatena Ruby」で Ruby を含む日記ファイルの一覧を出す
  • 似たような記事があったらそこにジャンプ
  • C-c C-l でそのエントリのリンクを作る
  • 元のエントリに戻ってきて関連リンクとしてヤンクする

追記

コメントで rubikitch さんから kill-new という関数を教えてもらったので早速書き直しておいた。
あとリンクを作ったときに何も反応がないのは分かりづらいかなと思ってミニバッファにメッセージを出すようにしてみた。
後で見直せるように書き直す前のスクリプトを貼っておく。
他に気になるところといえば、エントリ ID の装飾を消せてないところ。
format 通せばただの文字列になるのかと思って試してみたけどダメだった。
これはまた分かったときに直そうと思う。

(defun make-link-for-current-entry ()
  "現在のエントリのリンク(はてな http 記法)を作成し、キルリングに保存します。
保存されるリンクの例 [http://d.hatena.ne.jp/gan2/20080224/1203830553:title].

Make link (hatena-http-notation) for current entry,
for example [http://d.hatena.ne.jp/gan2/20080224/1203830553:title].
And save the link in the kill ring."
  (interactive)
  (save-excursion
    (let (entry-id)
      (forward-line)
      (if (re-search-backward "^\\*\\([0-9]+\\)\\*" nil t)
          (progn (setq entry-id (buffer-substring (match-beginning 1) (match-end 1)))
                 (setq kill-ring 
                       (cons (concat "[http://d.hatena.ne.jp/" hatena-usrid "/"
                                     (buffer-name) "/" entry-id ":title]\n") kill-ring))
                 (rotate-yank-pointer -1))
        (message "Error. Cannot make link.")))))

追記2

文字列の装飾は buffer-substring-no-properties を使えば消せることが分かった。
コメントで教えて頂いた plus さんありがとうございます!

 -- Function: buffer-substring-no-properties START END
     この関数は`buffer-substring'と同様であるが、テキスト属性をコピーせ
     ずに文字だけをコピーする点が異なる。

追記3

browse-kill-ring と併用するとちょっと問題があることが分かった。
エントリのリンクが kill-ring の2番目以降にあるとき (つまり最新のアイテムでないとき) に、browse-kill-ring を呼び出して kill-ring からエントリのリンクを RET で取り出そうとするとエラーが出る。
最新のアイテムの場合は RET で普通に取り出せる。ちょっと不思議。
kill-ring への格納は、標準関数の kill-new でやってるから kill-ring の問題ではないと思う。
browse-k1ill-ring は kill-ring を単純に利用しているわけではないみたい?
もしかしたら kill-summary でも同様の問題が起こるのかもしれない。