   (if-let (win (get-buffer-window "*Messages*"))
       (doom/popup-close win)
     (doom-popup-buffer (get-buffer "*Messages*"))))
+
+;;;###autoload
+(defun doom-popup-prop (prop &optional window)
+  (or (plist-get (or (if window
+                         (buffer-local-value 'doom-popup-rules (window-buffer window))
+                       doom-popup-rules)
+                     (window-parameter window 'popup))
+                 prop)
+      (cond ((eq prop :size)
+             shackle-default-size)
+            ((eq prop :align)
+             shackle-default-alignment))))
+
+;;;###autoload
+(defun doom-popup-side (&optional window)
+  (let ((align (doom-popup-prop :align window)))
+    (when (eq align t)
+      (setq align shackle-default-alignment))
+    (when (functionp align)
+      (setq align (funcall align)))
+    align))
+
+;;;###autoload
+(defun doom-popup-size (&optional window)
+  (let ((side (doom-popup-side window)))
+    (cond ((memq side '(left right))
+           (window-width window))
+          ((memq side '(above below))
+           (window-height window)))))
+
+(defun doom--popup-data (window)
+  (when-let (buffer (window-buffer window))
+    `(,(buffer-name buffer)
+      :file  ,(buffer-file-name buffer)
+      :rules ,(window-parameter window 'popup)
+      :size  ,(doom-popup-size window))))


;;;###autoload
(defun doom-popup-switch-to-buffer (buffer)
  (unless (doom-popup-p)
    (let ((popups (doom-popup-windows)))
      (unless popups

only close popups that have an :autoclose property in their rule (see
`shackle-rules')."
  (interactive)
  (when-let (popups (doom-popup-windows))
    (let ((orig-win (selected-window))
          doom-popup-remember-history)
      (setq doom-popup-history (mapcar #'doom--popup-data popups))
      (dolist (window popups)
        (when (or force-p
                  (called-interactively-p 'interactive)
                  (doom-popup-prop :autoclose window))
          (delete-window window))))))

;;;###autoload
(defun doom/popup-close-maybe ()
  "Close the current popup *if* its window doesn't have a noesc parameter."
  (interactive)
  (if (doom-popup-prop :noesc)
      (call-interactively
       (if (featurep 'evil)
           #'evil-force-normal-state
         #'keyboard-escape-quit))
    (delete-window)))

;;;###autoload
(defun doom/popup ()
  "Display currently selected buffer in a popup window."
  (interactive)
  (doom-popup-buffer (current-buffer) :align t :autokill t))

;;;###autoload
(defun doom/popup-toggle-messages ()
