linkd.elインストール
anything.elのソースに linkd.el が使われているのを見て、便利そうだったので導入してみた。
以下の2つの問題点あり。
何故かアイコンが表示されない
何か設定が足りないと思うので、後で調査する。
テキスト中の中途半端な lisp式が記述してあるとエラーになる
bm.el の .bm-repository など、テキスト中に中途半端な lisp式が記述してあるとエラーになる。
中途半端な lisp式の記述可能性のあるファイル(text-modeとか)モードフックに 'linkd-mode を加えるのを断念。
c++の例外catchみたいに、エラーが出てもヌルー出来ないものだろうか。。。
追記:
エラーの条件が絞り込めた。
中途半端なlisp式ではなく、おかしなlinkd式(?)があったときにエラーになる。
;; corresponding @*, not just to the next link (@* or @>).
↑linkd.elより
とか
(@* \"Foo bar baz\")
↑bm.elの保存ファイルより
発生場所は、font-lockの際の (linkd-render-link) 。
linkd.elを色づけする際にエラーになっているので、自分環境でしかこのエラーは起こっていない模様。
さて、どう対応するか。。
解決
font-lock時の (eval sexp) で落ちていたので、linkd-match を下記のように変更 (※この修正は正しくありません。下記の2008/10/2の追記を参照して下さい)
(defun linkd-match (limit) "Try to read link sexp between point and LIMIT. Return non-nil if a link is found. Set match-data appropriately." (let ((sexp nil)) (when (search-forward (concat "(" "@") limit t) (backward-char 2)) (let ((begin-point (point))) ;org (condition-case nil (setq sexp (read (current-buffer))) ((error nil))) (condition-case nil (let ( (tmp-sexp (read (current-buffer)))) (eval tmp-sexp) (setq sexp tmp-sexp)) ((error nil))) (when (string-match "@.*" (symbol-name (car-safe sexp))) (let ((begin-marker (make-marker)) (end-marker (make-marker))) (set-marker begin-marker begin-point) (set-marker end-marker (point)) (set-match-data (list begin-marker end-marker))) t))))
追記: 2008/09/29
エラーの発生機序が段々分かってきた。
まず、linkd.el 自体でエラーになる現象だが、add-hook をしない状態で、手動で M-x linkd-mode を行うと起こらない。
調べてみると、手動で linkd-mode に切り替えたときは linkd-match がコールされていない。
mode-hook で色づけされるときと、手動で linkd-modeに切り替えたときの色づけの機序が違うらしい。
多分、いい感じでfont-lockがコメントとしてはじいているような気がする。
それを裏付けるように、text-mode では、手動で linkd-mode にした場合もエラーになる。
段々面倒になってきたので、前回の修正でイイヤと思い始めてきた。。
追記: 2008/10/2
結局力業で、下記のような修正をすることで最終的な解決とした。
前回の修正だと、下記のような正しくないS式があった場合、それ以降のlinkd S式が色づけされないという問題があった。
(@
というか、他の人たちはエラー出てないんだろうか。。
ウチのVineでは、emacs -q で試してみてもエラーになっていたのに。。。
※2009/2/24追記
この不具合だか、emacsのバージョンに依存している事が発覚。
emacs-22.0だとNG
emacs-22.3だと問題なく動作していた。
トホホ。。
(defun linkd-match (limit) "Try to read link sexp between point and LIMIT. Return non-nil if a link is found. Set match-data appropriately." (catch 'found (while t (if (search-forward (concat "(" "@") limit t) (progn (backward-char 2) (let ((sexp nil) (begin-point (point))) (if (and (condition-case nil (setq sexp (read (current-buffer))) (error (if (end-of-buffer) (throw 'found nil) (goto-char (+ 1 begin-point))))) (condition-case nil (eval sexp) (error nil))) (progn (when (string-match "@.*" (symbol-name (car-safe sexp))) (let ((begin-marker (make-marker)) (end-marker (make-marker))) (set-marker begin-marker begin-point) (set-marker end-marker (point)) (set-match-data (list begin-marker end-marker))) (throw 'found t)) )))) (throw 'found nil))) ))
linkd.elの設定例
(require 'linkd) (define-key linkd-map (kbd "C-c , >") 'linkd-insert-tag) (define-key linkd-map (kbd "C-c , *") 'linkd-insert-star) (setq linkd-use-icons t) (setq linkd-icons-directory (concat my-lisp-directory "/linkd-icons")) (add-hook 'emacs-lisp-mode-hook 'linkd-mode) (add-hook 'lisp-mode-hook 'linkd-mode) (add-hook 'sh-mode-hook 'linkd-mode) (add-hook 'c-mode-common-hook 'linkd-mode)