読者です 読者をやめる 読者になる 読者になる

EmacsLispで遊ぶ

プログラミング


明けましておめでとうございます。


新年早々、ノロウイルスに感染したかのような症状に見舞われていたせいで、
予定していたタスクの半分もこなせていない今日この頃、みなさん、いかがお過ごしですか?
とまあ、テキトーな挨拶はこれくらいにして、今日はEmacsLisp(以下、elisp)のお話。


Emacsを本格的に使うようになって1年と半年ぐらい経って、最近、既存のelispによる拡張だけでは
かゆいところに手が届かないのに我慢できなくなって、自分で拡張しはじめたりしてるのですが、
elispのオブジェクトの扱い方がわからないとかわめいています。(特にバッファとかフレームあたりが)

で、何が我慢できなくなったのかと言うと、Emacsはetagで作成したインデックス内の関数のあるファイルに
find-tagでジャンプする際、デフォルトでは単にswitch-to-bufferで現在開いているバッファを切り替える
のですが、ElScreenを使っているんだから別のファイル開くときは別のスクリーンで開きたいよな、とか思ったわけです。
さらに、該当するバッファが既に開いている場合はそのバッファにジャンプするとか。


で、やってみた。

(defun switch-to-elscreen-create (buf)
  (defun create-new-buf (buf)
    (elscreen-create)
    (switch-to-buffer buf))
  (defun switch-to-elscreen-create-inner (screen-list buf)
    (cond ((null (elscreen-get-window-configuration (car screen-list)))
           nil)
          ((equal (car screen-list) (elscreen-find-screen-by-buffer (buffer-name buf)))
           (elscreen-goto (car screen-list)))
          (t
           (switch-to-elscreen-create-inner (cdr screen-list) buf))))
  (if (null (switch-to-elscreen-create-inner (elscreen-get-screen-list) buf))
      (create-new-buf buf)
    t))

(defun find-tag (tagname &optional next-p regexp-p)
  (interactive (find-tag-interactive "Find tag: "))
  (let ((buf (find-tag-noselect tagname next-p regexp-p)))
    (condition-case
        nil
        (switch-to-elscreen-create buf)
      (error (pop-to-buffer buf)))))


コードはこれだけだが、ここに至るまで3〜4時間orz。edebug-defunの存在に気付いていればもうちょっと早く終ったかも。

動かすにはElScreenとetagが必要です。