popwin.el でポップアップ表示したバッファを再度ポップアップさせる

popwin.elを導入しみました。こういうの欲しかったけど自分じゃ作れない...。


で、一度ポップアップウィンドウで表示したバッファをもう一度、ポップアップウィンドウで表示させたい気がしたので慣れない elisp を書いてみた。


↓こんなの。F8 を押すと popwin:special-display-config に設定したポップアップ対象のバッファをポップアップで表示させます。もう一度 F8 を押すと別のポップアップ対象バッファに切り替わります。(elisp はほとんど書かないので変な書き方をしているだろうと思います)

(defvar my-popwin:seq-store-count 0)
(defvar my-popwin:buffer-list '())

(defun my-popwin:filter (pred lst)
  (if (null lst) '()
    (if (funcall pred (car lst))
        (cons (car lst) (my-popwin:filter pred (cdr lst)))
      (my-popwin:filter pred (cdr lst)))))

(defun my-popwin:repopup-target-p (buffer)
  (loop with name = (buffer-name buffer)
        with mode = (with-current-buffer buffer major-mode)
        for (pattern . keywords) in popwin:special-display-config
        thereis
        (destructuring-bind (&key regexp width height position noselect)
            keywords
          (cond
           ((and (stringp pattern)
                 regexp)
            (string-match pattern name))
           ((stringp pattern)
            (string= pattern name))
           ((symbolp pattern)
            (eq pattern mode))
           (t (error "Invalid pattern: %s" pattern))))))

(defun my-popwin:repopup-target-buffer-list ()
  (my-popwin:filter
   'my-popwin:repopup-target-p
   (buffer-list)))


(defun my-popwin:next-buffer ()
  (if (eq last-command this-command)
      (incf my-popwin:seq-store-count)
    (setq my-popwin:seq-store-count 0)
    (setq my-popwin:buffer-list (my-popwin:repopup-target-buffer-list)))
  (if (< 0 (length my-popwin:buffer-list))
      (nth (mod my-popwin:seq-store-count (length my-popwin:buffer-list))
           my-popwin:buffer-list)
    '()))

(defun my-popwin:repopup-window ()
  (interactive)
  (let ((buffer (my-popwin:next-buffer)))
    (unless (null buffer)
      (popwin:close-popup-window)
      (popwin:display-buffer buffer t))))

(global-set-key (kbd "<f8>") 'my-popwin:repopup-window)