Major refactor of ui/popup

+ Make it pass tests
+ Changes the behavior and arguments of functions passed to :autosave,
  :ttl, and :modeline.
+ Updated the documentation of set-popup-rule! to reflect these changes
+ Phase out map.el usage as per f6dc6ac7
This commit is contained in:
Henrik Lissner 2018-06-23 22:18:44 +02:00
parent f11bd617cd
commit 618358413b
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
2 changed files with 147 additions and 132 deletions

View file

@ -33,6 +33,7 @@ the buffer is visible, then set another timer and try again later."
default window parameters for popup windows, clears leftover transient timers
and enables `+popup-buffer-mode'."
(with-selected-window window
(setq alist (delq (assq 'actions alist) alist))
(when (and alist +popup--populate-wparams)
;; Emacs 26+ will automatically map the window-parameters alist entry to
;; the popup window, so we need this for Emacs 25.x users
@ -58,58 +59,61 @@ and enables `+popup-buffer-mode'."
`transient' window parameter (see `+popup-window-parameters').
+ And finally deletes the window!"
(let ((buffer (window-buffer window))
(inhibit-quit t)
ttl)
(when (and (buffer-file-name buffer)
(buffer-modified-p buffer)
(or (+popup-parameter-fn 'autosave window buffer)
(y-or-n-p "Popup buffer is modified. Save it?")))
(with-current-buffer buffer (save-buffer)))
(set-buffer-modified-p nil)
(inhibit-quit t))
(and (buffer-file-name buffer)
(buffer-modified-p buffer)
(let ((autosave (+popup-parameter 'autosave window)))
(cond ((eq autosave 't))
((null autosave)
(y-or-n-p "Popup buffer is modified. Save it?"))
((functionp autosave)
(funcall autosave buffer))))
(with-current-buffer buffer (save-buffer)))
(let ((ignore-window-parameters t))
(delete-window window))
(unless (window-live-p window)
(with-current-buffer buffer
(set-buffer-modified-p nil)
(+popup-buffer-mode -1)
;; t = default
;; integer = ttl
;; nil = no timer
(unless +popup--inhibit-transient
(setq ttl (+popup-parameter-fn 'ttl window buffer))
(when ttl
(when (eq ttl t)
(setq ttl (or (plist-get +popup-defaults :ttl)
0)))
(cl-assert (integerp ttl) t)
(if (= ttl 0)
(+popup--kill-buffer buffer 0)
(add-hook 'kill-buffer-hook #'+popup|kill-buffer-hook nil t)
(setq +popup--timer
(run-at-time ttl nil #'+popup--kill-buffer
buffer ttl)))))))))
(let ((ttl (+popup-parameter 'ttl window)))
(when (eq ttl 't)
(setq ttl (plist-get +popup-defaults :ttl)))
(cond ((null ttl))
((functionp ttl)
(funcall ttl buffer))
((not (integerp ttl))
(signal 'wrong-type-argument (list 'integerp ttl)))
((= ttl 0)
(+popup--kill-buffer buffer 0))
((add-hook 'kill-buffer-hook #'+popup|kill-buffer-hook nil t))
((setq +popup--timer
(run-at-time ttl nil #'+popup--kill-buffer
buffer ttl))))))))))
(defun +popup--normalize-alist (alist)
"Merge `+popup-default-alist' and `+popup-default-parameters' with ALIST."
(let ((alist ; handle defaults
(cl-remove-duplicates
(append alist +popup-default-alist)
:key #'car :from-end t))
(parameters
(cl-remove-duplicates
(append (cdr (assq 'window-parameters alist))
+popup-default-parameters)
:key #'car :from-end t)))
;; handle `size'
(when-let* ((size (cdr (assq 'size alist)))
(side (or (cdr (assq 'side alist)) 'bottom))
(param (if (memq side '(left right))
'window-width
'window-height)))
(setq alist (map-delete alist 'size))
(map-put alist param size))
(setcdr (assq 'window-parameters alist)
(cl-remove-if #'null parameters :key #'cdr))
(cl-remove-if #'null alist :key #'cdr)))
(when alist
(let ((alist ; handle defaults
(cl-remove-duplicates
(append alist +popup-default-alist)
:key #'car :from-end t))
(parameters
(cl-remove-duplicates
(append (cdr (assq 'window-parameters alist))
+popup-default-parameters)
:key #'car :from-end t)))
;; handle `size'
(when-let* ((size (cdr (assq 'size alist)))
(side (or (cdr (assq 'side alist)) 'bottom))
(param (if (memq side '(left right))
'window-width
'window-height)))
(setq list (assq-delete-all 'size alist))
(setcdr (assq param alist) size))
(setcdr (assq 'window-parameters alist)
parameters)
alist)))
;;
@ -120,23 +124,21 @@ and enables `+popup-buffer-mode'."
(defun +popup-buffer-p (&optional buffer)
"Return non-nil if BUFFER is a popup buffer. Defaults to the current buffer."
(when +popup-mode
(unless buffer
(setq buffer (current-buffer)))
(cl-assert (bufferp buffer) t)
(and (buffer-live-p buffer)
(buffer-local-value '+popup-buffer-mode buffer)
buffer)))
(let ((buffer (or buffer (current-buffer))))
(and (bufferp buffer)
(buffer-live-p buffer)
(buffer-local-value '+popup-buffer-mode buffer)
buffer))))
;;;###autoload
(defun +popup-window-p (&optional window)
"Return non-nil if WINDOW is a popup window. Defaults to the current window."
(when +popup-mode
(unless window
(setq window (selected-window)))
(cl-assert (windowp window) t)
(and (window-live-p window)
(window-parameter window 'popup)
window)))
(let ((window (or window (selected-window))))
(and (windowp window)
(window-live-p window)
(window-parameter window 'popup)
window))))
;;;###autoload
(defun +popup-buffer (buffer &optional alist)
@ -216,11 +218,14 @@ restoring it if `+popup-buffer-mode' is disabled."
+ If a function, it takes the current buffer as its argument and must return one
of the above values."
(when (bound-and-true-p +popup-buffer-mode)
(let ((modeline (+popup-parameter-fn 'modeline nil (current-buffer))))
(let ((modeline (+popup-parameter 'modeline)))
(cond ((eq modeline 't))
((or (eq modeline 'nil)
(null modeline))
;; TODO use `mode-line-format' window parameter instead (emacs 26+)
(hide-mode-line-mode +1))
((functionp modeline)
(funcall modeline))
((symbolp modeline)
(when-let* ((hide-mode-line-format (doom-modeline modeline)))
(hide-mode-line-mode +1)))))))
@ -246,9 +251,9 @@ restoring it if `+popup-buffer-mode' is disabled."
(defun +popup|cleanup-rules ()
"Cleans up any duplicate popup rules."
(interactive)
(cl-delete-duplicates
+popup--display-buffer-alist
:key #'car :test #'equal :from-end t)
(setq +popup--display-buffer-alist
(cl-delete-duplicates +popup--display-buffer-alist
:key #'car :test #'equal :from-end t))
(when +popup-mode
(setq display-buffer-alist +popup--display-buffer-alist)))
@ -291,16 +296,15 @@ This will do nothing if the popup's `quit' window parameter is either nil or
(interactive
(list (selected-window)
current-prefix-arg))
(unless window
(setq window (selected-window)))
(when (and (+popup-window-p window)
(or force-p
(memq (+popup-parameter-fn 'quit window window)
'(t current))))
(when +popup--remember-last
(+popup--remember (list window)))
(delete-window window)
t))
(let ((window (or window (selected-window))))
(when (and (+popup-window-p window)
(or force-p
(memq (+popup-parameter-fn 'quit window window)
'(t current))))
(when +popup--remember-last
(+popup--remember (list window)))
(delete-window window)
t)))
;;;###autoload
(defun +popup/close-all (&optional force-p)
@ -426,7 +430,7 @@ Accepts the same arguments as `display-buffer-in-side-window'. You must set
(lambda (_side) (frame-root-window (selected-frame)))))
(when-let* ((window (window--make-major-side-window buffer side slot alist)))
(set-window-parameter window 'window-vslot vslot)
(map-put window-persistent-parameters 'window-vslot 'writable)
(add-to-list 'window-persistent-parameters '(window-vslot . writable))
window)))
(t
;; Scan windows on SIDE.
@ -570,11 +574,11 @@ and may be called only if no window on SIDE exists yet."
;; Initialize `window-side' parameter of new window to SIDE and
;; make that parameter persistent.
(set-window-parameter window 'window-side side)
(map-put window-persistent-parameters 'window-side 'writable)
(add-to-list 'window-persistent-parameters '(window-side . writable))
;; Install `window-slot' parameter of new window and make that
;; parameter persistent.
(set-window-parameter window 'window-slot slot)
(map-put window-persistent-parameters 'window-slot 'writable)
(add-to-list 'window-persistent-parameters '(window-slot . writable))
;; Auto-adjust height/width of new window unless a size has been
;; explicitly requested.
(unless (if left-or-right