core-popups: refactor window parameters & popup init

This commit is contained in:
Henrik Lissner 2017-02-22 21:54:10 -05:00
parent 8271342b2e
commit 92fb1e3417
2 changed files with 93 additions and 84 deletions

View file

@ -5,9 +5,7 @@
(defun doom-popup-p (&optional window)
"Return t if WINDOW is a popup. Uses current window if WINDOW is omitted."
(let ((window (or window (selected-window))))
(and window
(or (window-parameter window 'popup)
(buffer-local-value 'doom-popup-mode (window-buffer window))))))
(and window (window-parameter window 'popup))))
;;;###autoload
(defun doom-popup-buffer (buffer &rest plist)
@ -35,7 +33,9 @@ possible rules."
;;;###autoload
(defun doom/popup-restore ()
"Restore the last popups."
"Restore the last popups. If the buffers have been killed, and represented
real files, they will be restored. Special buffers or buffers with non-nil
:autokill properties will not be."
(interactive)
(unless doom-popup-history
(error "No popups to restore"))
@ -72,14 +72,11 @@ possible rules."
;;;###autoload
(defun doom/popup-close-all ()
"Closes all open popups. If DONT-KILL is non-nil, don't kill their buffers."
"Closes all open popups."
(interactive)
(let* ((orig-win (selected-window))
(popups (cl-remove-if-not (lambda (win) (and (doom-popup-p win)
(not (eq win orig-win))))
(window-list))))
(when popups
(setq doom-popup-history (mapcar 'doom--popup-data (doom-popup-windows)))
(let ((orig-win (selected-window)))
(when-let (popups (doom-popup-windows))
(setq doom-popup-history (mapcar 'doom--popup-data popups))
(let (doom-popup-remember-history)
(mapc 'delete-window popups)))))
@ -88,7 +85,7 @@ possible rules."
"Close the current popup *if* its window doesn't have a noesc parameter."
(interactive)
(let ((window (selected-window)))
(if (window-parameter window 'noesc)
(if (window-parameter window :noesc)
(call-interactively (if (featurep 'evil)
'evil-force-normal-state
'keyboard-escape-quit))

View file

@ -34,6 +34,10 @@
map)
"Active keymap in popup windows.")
(defvar doom-popup-window-parameters '(:noesc :modeline :autokill)
"A list of window parameters that are set (and cleared) when `doom-popup-mode
is enabled/disabled.'")
(@def-setting :popup (&rest rules)
"Prepend a new popup rule to `shackle-rules'."
(if (cl-every 'listp rules)
@ -61,7 +65,7 @@
("*Pp Eval Output*" :size 0.3 :autokill t)
("*Apropos*" :size 0.3)
("*Backtrace*" :size 25 :noselect t)
("*Help*" :size 16 :autokill t)
("*Help*" :size 16)
("*Messages*" :size 10)
("*Warnings*" :size 10 :noselect t :autokill t)
("*command-log*" :size 28 :noselect t :align right)
@ -73,14 +77,9 @@
(tabulated-list-mode :noesc t)))
:config
(shackle-mode 1))
(shackle-mode 1)
;;
;; Modifications
;;
(defun doom*shackle-always-align (plist)
(defun doom*shackle-always-align (plist)
"Ensure popups are always aligned and selected by default. Eliminates the need
for :align t on every rule."
(when plist
@ -90,70 +89,86 @@ for :align t on every rule."
(plist-member plist :noselect))
(plist-put plist :select t)))
plist)
(advice-add 'shackle--match :filter-return 'doom*shackle-always-align)
(advice-add 'shackle--match :filter-return 'doom*shackle-always-align))
;;
;; Integration
;;
;; Tell `window-state-get' and `current-window-configuration' to persist these
;; custom parameters. Allows `persp-mode' to remember popup states.
(nconc window-persistent-parameters
'((popup . writable)
(noesc . writable)
(autokill . writable)))
;; custom parameters. Helpful for `persp-mode' to persist popup windows.
(push (cons 'no-other-window 'writable) window-persistent-parameters)
(dolist (param doom-popup-window-parameters)
(push (cons param 'writable) window-persistent-parameters))
(define-minor-mode doom-popup-mode
"Minor mode for popup windows."
:init-value nil
:keymap doom-popup-mode-map
;; Don't show modeline in popup windows without a :modeline rule. If one
;; exists and it's a symbol, use `doom-modeline' to grab the format. If
;; non-nil, show the mode-line as normal. If nil (or omitted), then hide the
;; modeline entirely.
(if (and (not doom-popup-mode)
doom-hide-modeline-mode)
(doom-hide-modeline-mode -1)
(let ((window (selected-window)))
;; Major mode changes (and other things) may call
;; `kill-all-local-variables', turning off things like `doom-popup-mode'.
;; This prevents that.
(put 'doom-popup-mode 'permanent-local doom-popup-mode)
;; Ensure that buffer-opening functions/commands (like
;; `switch-to-buffer-other-window' won't use this window).
(set-window-parameter window 'no-other-window doom-popup-mode)
;; Makes popup window resist interactively changing its buffer.
(set-window-dedicated-p window doom-popup-mode)
(cond (doom-popup-mode
;; Don't show modeline in popup windows without a :modeline rule. If
;; one exists and it's a symbol, use `doom-modeline' to grab the
;; format. If non-nil, show the mode-line as normal. If nil (or
;; omitted, by default), then hide the modeline entirely.
(let ((modeline (plist-get doom-popup-rules :modeline)))
(cond ((or (eq modeline 'nil)
(not modeline))
(doom-hide-modeline-mode +1))
((symbolp modeline)
(let ((doom--hidden-modeline-format (doom-modeline modeline)))
(doom-hide-modeline-mode +1)))))))
(put 'doom-popup-mode 'permanent-local t)
(doom-hide-modeline-mode +1)))))
;; Save metadata into window parameters so it can be saved by window
;; config persisting plugins like workgroups or persp-mode.
(set-window-parameter window 'popup (or doom-popup-rules t))
(when doom-popup-rules
(dolist (param doom-popup-window-parameters)
(when-let (val (plist-get doom-popup-rules param))
(set-window-parameter window param val)))))
(t
;; show modeline
(when doom-hide-modeline-mode
(doom-hide-modeline-mode -1))
;; Ensure window parameters are cleaned up
(set-window-parameter window 'popup nil)
(dolist (param doom-popup-window-parameters)
(set-window-parameter window param nil))))))
;; Hide modeline in completion popups
(@add-hook (completion-in-region-mode completion-list-mode) 'doom-hide-modeline-mode)
(defun doom-popup--init (window &optional plist)
"Initializes a window as a popup window. Sets custom window parameters and
enables `doom-popup-mode'."
;;
(defun doom*popup-init (orig-fn &rest args)
"Initializes a window as a popup window by enabling `doom-popup-mode' in it.
Returns the window."
(unless (doom-popup-p)
(setq doom-popup-other-window (selected-window)))
(let ((plist (or (nth 2 args)
(and (bufferp (car args))
(shackle-match (window-buffer (car args))))))
(window (apply orig-fn args)))
(unless window
(error "No window was found for %s: %s" (car args) plist))
(unless plist
(setq plist (shackle-match (window-buffer window))))
(mapc (lambda (cfg) (set-window-parameter window (car cfg) (cdr cfg)))
(append `((popup . ,plist)
(no-other-window . ,t))
(when (plist-get plist :noesc)
`((noesc . ,t)))
(when (plist-get plist :autokill)
`((autokill . ,t)))))
(error "No popup window was found for %s: %s" (car args) plist))
(with-selected-window window
(unless (eq plist t)
(setq-local doom-popup-rules plist))
(doom-popup-mode +1))
window)
;;
(defun doom*popup-init (orig-fn &rest args)
"Invokes `doom-popup--init' on windows that qualify as popups. Returns the window."
(unless (doom-popup-p)
(setq doom-popup-other-window (selected-window)))
(doom-popup--init (apply orig-fn args) (nth 2 args)))
window))
(defun doom*popups-save (orig-fn &rest args)
"Puts aside all popups before executing the original function, usually to
prevent popups from messaging up the UI (or vice versa)."
"Sets aside all popups before executing the original function, usually to
prevent the popup(s) from messing up the UI (or vice versa)."
(let ((in-popup-p (doom-popup-p))
(popups (doom-popup-windows))
(doom-popup-remember-history t))
@ -166,25 +181,22 @@ prevent popups from messaging up the UI (or vice versa)."
(unless in-popup-p
(select-window origin)))))))
(defun doom*delete-popup-window (orig-fn &rest args)
(defun doom*delete-popup-window (&optional window)
"Ensure that popups are deleted properly, and killed if they have :autokill
properties."
(let ((window (or (car args) (selected-window))))
(let ((window (or window (selected-window))))
(when (doom-popup-p window)
(when doom-popup-remember-history
(setq doom-popup-history (list (doom--popup-data window))))
(set-window-dedicated-p window nil)
(if (window-parameter window 'autokill)
(kill-buffer (window-buffer window))
(let ((autokill-p (window-parameter window :autokill)))
(with-selected-window window
(doom-popup-mode -1)))
(mapc (lambda (cfg) (set-window-parameter window cfg nil))
'(popup no-other-window noesc autokill))))
(apply orig-fn args))
(doom-popup-mode -1)
(when autokill-p
(kill-buffer (current-buffer))))))))
(advice-add 'shackle-display-buffer :around 'doom*popup-init)
(advice-add 'balance-windows :around 'doom*popups-save)
(advice-add 'delete-window :around 'doom*delete-popup-window)
(advice-add 'delete-window :before 'doom*delete-popup-window)
;;