💥 Replace core-popup with new feature/popup module
This is a breaking change! Update your :popup settings. Old ones will throw errors! Doom's new popup management system casts off its shackles (hur hur) and replaces them with the monster that is `display-buffer-alist`, and window parameters. However, this is highly experimental! Expect edge cases. Particularly with org-mode and magit (or anything that does its own window management). Relevant to #261, #263, #325
This commit is contained in:
parent
065091bdca
commit
91357a3e5d
33 changed files with 631 additions and 1038 deletions
|
@ -3,9 +3,7 @@
|
|||
(def-package! realgud
|
||||
:commands (realgud:gdb realgud:trepanjs realgud:bashdb realgud:zshdb)
|
||||
:config
|
||||
(set! :popup
|
||||
'("^\\*\\(g\\|zsh\\|bash\\)db.*?\\*$" :size 20 :regexp t)
|
||||
'("^\\*trepanjs.*?\\*$" :size 20 :regexp t))
|
||||
(set! :popup "^\\*\\(?trepanjs:\\(?:g\\|zsh\\|bash\\)db\\)" '((size . 20)))
|
||||
|
||||
;; TODO Temporary Ex commands for the debugger
|
||||
;; (def-tmp-excmd! doom:def-debug-on doom:def-debug-off
|
||||
|
|
|
@ -16,10 +16,6 @@
|
|||
function that creates and returns the REPL buffer."
|
||||
`(push (cons ,mode ,command) +eval-repls))
|
||||
|
||||
(set! :popup
|
||||
'(:custom (lambda (b &rest _) (buffer-local-value '+eval-repl-mode b)))
|
||||
:size 16 :noesc t)
|
||||
|
||||
|
||||
;;
|
||||
;; Evaluation
|
||||
|
@ -70,7 +66,8 @@ function that creates and returns the REPL buffer."
|
|||
(unless (boundp 'display-line-numbers)
|
||||
(add-hook 'quickrun--mode-hook #'nlinum-mode))
|
||||
:config
|
||||
(set! :popup "*quickrun*" :size 6 :autokill t :autoclose t)
|
||||
(set! :popup "^\\*\\(?:doom eval\\|Pp Eval Output\\|quickrun\\)"
|
||||
'((window-height . 10)) '((transient . 0)))
|
||||
|
||||
(defun +eval*quickrun-auto-close (&rest _)
|
||||
"Allows us to silently re-run quickrun from within the quickrun buffer."
|
||||
|
|
|
@ -32,14 +32,14 @@
|
|||
there and there is only one window, split in that direction and place this
|
||||
window there. If there are no windows and this isn't the only window, use
|
||||
evil-window-move-* (e.g. `evil-window-move-far-left')"
|
||||
(when (doom-popup-p)
|
||||
(doom/popup-raise))
|
||||
(let* ((this-window (get-buffer-window))
|
||||
(when (window-dedicated-p)
|
||||
(user-error "Cannot swap a dedicated window"))
|
||||
(let* ((this-window (selected-window))
|
||||
(this-buffer (current-buffer))
|
||||
(that-window (windmove-find-other-window direction nil this-window))
|
||||
(that-buffer (window-buffer that-window)))
|
||||
(when (or (minibufferp that-buffer)
|
||||
(doom-popup-p that-window))
|
||||
(window-dedicated-p this-window))
|
||||
(setq that-buffer nil that-window nil))
|
||||
(if (not (or that-window (one-window-p t)))
|
||||
(funcall (pcase direction
|
||||
|
|
|
@ -42,9 +42,8 @@
|
|||
(add-hook 'doom-init-hook #'evil-mode)
|
||||
(evil-select-search-module 'evil-search-module 'evil-search)
|
||||
|
||||
(set! :popup
|
||||
'("*evil-registers*" :size 0.3)
|
||||
'("*Command Line*" :size 8))
|
||||
(set! :popup "^\\*evil-registers" '((size . 0.3)))
|
||||
(set! :popup "^\\*Command Line" '((size . 8)))
|
||||
|
||||
;; Don't interfere with localleader key
|
||||
(define-key evil-motion-state-map "\\" nil)
|
||||
|
|
|
@ -91,8 +91,7 @@ properties:
|
|||
(after! xref
|
||||
;; By default, `etags--xref-backend' is the default xref backend. No need.
|
||||
;; We'll set these up ourselves in other modules.
|
||||
(setq-default xref-backend-functions '(t))
|
||||
(set! :popup "*xref*" :noselect t :autokill t :autoclose t))
|
||||
(setq-default xref-backend-functions '(t)))
|
||||
|
||||
(defun +lookup|init-xref-backends ()
|
||||
"Set `+lookup-current-functions' for the current buffer.
|
||||
|
|
49
modules/feature/popup/README.org
Normal file
49
modules/feature/popup/README.org
Normal file
|
@ -0,0 +1,49 @@
|
|||
#+TITLE: :feature popup
|
||||
|
||||
A short summary about what this module does.
|
||||
|
||||
If necessary, include a longer description below it that goes into more detail. This may be as long as you like.
|
||||
|
||||
+ If possible, include a list of features
|
||||
+ Include links to major plugins that the module uses, if applicable
|
||||
+ Use links whenever you can
|
||||
+ Mention dependencies on other modules here
|
||||
|
||||
* Table of Contents :TOC:
|
||||
- [[#install][Install]]
|
||||
- [[#main-dependencies][Main dependencies]]
|
||||
- [[#extra-dependencies][Extra Dependencies]]
|
||||
- [[#configuration][Configuration]]
|
||||
- [[#usage][Usage]]
|
||||
- [[#appendix][Appendix]]
|
||||
- [[#commands][Commands]]
|
||||
- [[#hacks][Hacks]]
|
||||
|
||||
* Install
|
||||
** Main dependencies
|
||||
*** MacOS
|
||||
#+BEGIN_SRC sh :tangle (if (doom-system-os 'macos) "yes")
|
||||
brew install x
|
||||
#+END_SRC
|
||||
|
||||
*** Arch Linux
|
||||
#+BEGIN_SRC sh :dir /sudo:: :tangle (if (doom-system-os 'arch) "yes")
|
||||
sudo pacman --needed --noconfirm -S X
|
||||
#+END_SRC
|
||||
|
||||
** Extra Dependencies
|
||||
+ A
|
||||
+ B
|
||||
+ C
|
||||
|
||||
#+BEGIN_SRC sh
|
||||
Y install A B C
|
||||
#+END_SRC
|
||||
|
||||
* Configuration
|
||||
|
||||
* Usage
|
||||
|
||||
* Appendix
|
||||
** Commands
|
||||
** Hacks
|
328
modules/feature/popup/autoload.el
Normal file
328
modules/feature/popup/autoload.el
Normal file
|
@ -0,0 +1,328 @@
|
|||
;;; feature/popup/autoload.el -*- lexical-binding: t; -*-
|
||||
|
||||
(defun +popup--cancel-buffer-timer ()
|
||||
"Cancel the current buffer's transient timer."
|
||||
(when (timerp +popup--timer)
|
||||
(message "Cancelled timer")
|
||||
(cancel-timer +popup--timer)
|
||||
(setq +popup--timer nil))
|
||||
t)
|
||||
|
||||
(defun +popup--remember (windows)
|
||||
"Remember WINDOWS (a list of windows) for later restoration."
|
||||
(cl-assert (cl-every #'windowp windows) t)
|
||||
(setq +popup--last
|
||||
(cl-loop for w in windows
|
||||
collect (list (window-buffer w)
|
||||
(window-parameter w 'alist)
|
||||
(window-state-get w)))))
|
||||
|
||||
(defun +popup--kill-buffer (buffer)
|
||||
"Tries to kill BUFFER, as was requested by a transient timer. If it fails, eg.
|
||||
the buffer is visible, then set another timer and try again later."
|
||||
(when (buffer-live-p buffer)
|
||||
(if (get-buffer-window buffer)
|
||||
(with-current-buffer buffer
|
||||
(setq +popup--timer
|
||||
(run-at-time (timer--time +popup--timer)
|
||||
nil #'+popup--kill-buffer buffer)))
|
||||
(with-demoted-errors "Error killing transient buffer: %s"
|
||||
(let ((inhibit-message (not doom-debug-mode)))
|
||||
(message "Cleaned up transient buffer: %s" buffer))
|
||||
(kill-buffer buffer)))))
|
||||
|
||||
(defun +popup--init (window alist)
|
||||
"Initializes a popup window. Run any time a popup is opened. It sets the
|
||||
default window parameters for popup windows, clears leftover transient timers
|
||||
and enables `+popup-buffer-mode'."
|
||||
(with-selected-window window
|
||||
(set-window-parameter window 'no-other-window t)
|
||||
(set-window-parameter window 'delete-window #'+popup--destroy)
|
||||
(set-window-parameter window 'alist alist)
|
||||
(window-preserve-size
|
||||
window (memq (window-parameter window 'window-side) '(left right)) t)
|
||||
(+popup--cancel-buffer-timer)
|
||||
(+popup-buffer-mode +1)))
|
||||
|
||||
(defun +popup--destroy (window)
|
||||
"Do housekeeping before destroying a popup window.
|
||||
|
||||
+ Disables `+popup-buffer-mode' so that any hooks attached to it get a chance to
|
||||
run and do cleanup of its own.
|
||||
+ Either kills the buffer or sets a transient timer, if the window has a
|
||||
`transient' window parameter (see `+popup-window-parameters').
|
||||
+ And finally deletes the window!"
|
||||
(let ((ttl (+popup-parameter 'transient window))
|
||||
(buffer (window-buffer window)))
|
||||
(let ((ignore-window-parameters t))
|
||||
(delete-window window))
|
||||
(unless (window-live-p window)
|
||||
(with-current-buffer buffer
|
||||
(+popup-buffer-mode -1)
|
||||
;; t = default
|
||||
;; integer = ttl
|
||||
;; nil = no timer
|
||||
(when ttl
|
||||
(when (eq ttl t)
|
||||
(setq ttl +popup-ttl))
|
||||
(cl-assert (integerp ttl) t)
|
||||
(if (= ttl 0)
|
||||
(+popup--kill-buffer buffer)
|
||||
(setq +popup--timer
|
||||
(run-at-time ttl nil #'+popup--kill-buffer buffer))))))))
|
||||
|
||||
(defun +popup--normalize-alist (alist)
|
||||
"Merge `+popup-default-alist' and `+popup-default-parameters' with ALIST."
|
||||
(if (not alist)
|
||||
(setq alist +popup-default-alist)
|
||||
(let* ((alist (map-merge 'list +popup-default-alist alist))
|
||||
(params (map-merge 'list
|
||||
+popup-default-parameters
|
||||
(cdr (assq 'window-parameters alist)))))
|
||||
(setq alist (assq-delete-all 'window-parameters alist))
|
||||
(push (cons 'window-parameters params) alist)
|
||||
(nreverse alist))))
|
||||
|
||||
|
||||
;;
|
||||
;; Public library
|
||||
;;
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup-p (&optional target)
|
||||
"Return t if TARGET is a popup window or buffer. If TARGET is nil, use the
|
||||
current buffer."
|
||||
(unless target
|
||||
(setq target (current-buffer)))
|
||||
(cond ((windowp target)
|
||||
(+popup-p (window-buffer target)))
|
||||
((bufferp target)
|
||||
(buffer-local-value '+popup-buffer-mode target))
|
||||
(t
|
||||
(error "Expected a window/buffer, got %s (%s)"
|
||||
(type-of target) target))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup-buffer (buffer &optional alist)
|
||||
"Open BUFFER in a popup window. ALIST describes its features."
|
||||
(let* ((old-window (selected-window))
|
||||
(alist (+popup--normalize-alist alist))
|
||||
(new-window (or (display-buffer-reuse-window buffer alist)
|
||||
(display-buffer-in-side-window buffer alist))))
|
||||
(+popup--init new-window alist)
|
||||
(select-window
|
||||
(if (+popup-parameter 'select new-window)
|
||||
new-window
|
||||
old-window))
|
||||
new-window))
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup-parameter (parameter &optional window)
|
||||
"Fetch the window parameter of WINDOW"
|
||||
(window-parameter (or window (selected-window)) parameter))
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup-windows ()
|
||||
"Returns a list of all popup windows."
|
||||
(cl-remove-if-not #'+popup-p (window-list)))
|
||||
|
||||
|
||||
;;
|
||||
;; Minor mode
|
||||
;;
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode +popup-mode
|
||||
"Global minor mode for popups."
|
||||
:init-value nil
|
||||
:global t
|
||||
:keymap +popup-mode-map
|
||||
(cond (+popup-mode
|
||||
(add-hook 'doom-unreal-buffer-functions #'+popup-p)
|
||||
(add-hook '+evil-esc-hook #'+popup|close-on-escape t)
|
||||
(setq +popup--old-display-buffer-alist display-buffer-alist
|
||||
display-buffer-alist +popup--display-buffer-alist)
|
||||
(dolist (prop +popup-window-parameters)
|
||||
(push (cons prop 'writeable) window-persistent-parameters)))
|
||||
(t
|
||||
(remove-hook 'doom-unreal-buffer-functions #'+popup-p)
|
||||
(remove-hook '+evil-esc-hook #'+popup|close-on-escape)
|
||||
(setq display-buffer-alist +popup--old-display-buffer-alist)
|
||||
(dolist (prop +popup-window-parameters)
|
||||
(assq-delete-all prop window-persistent-parameters)))))
|
||||
|
||||
;;;###autoload
|
||||
(define-minor-mode +popup-buffer-mode
|
||||
"Minor mode for popup windows."
|
||||
:init-value nil
|
||||
:keymap +popup-buffer-mode-map)
|
||||
|
||||
|
||||
;;
|
||||
;; Hooks
|
||||
;;
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup|adjust-fringes ()
|
||||
"Hides the fringe in popup windows, restoring them if `+popup-buffer-mode' is
|
||||
disabled."
|
||||
(let ((f (if +popup-buffer-mode 0 doom-fringe-size)))
|
||||
(set-window-fringes nil f f fringes-outside-margins)))
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup|set-modeline ()
|
||||
"Don't show modeline in popup windows without a `modeline' window-parameter.
|
||||
|
||||
+ 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 (the default)."
|
||||
(if +popup-buffer-mode
|
||||
(let ((modeline (+popup-parameter 'modeline)))
|
||||
(cond ((or (eq modeline 'nil)
|
||||
(not modeline))
|
||||
(doom-hide-modeline-mode +1))
|
||||
((and (symbolp modeline)
|
||||
(not (eq modeline 't)))
|
||||
(setq-local doom--modeline-format (doom-modeline modeline))
|
||||
(when doom--modeline-format
|
||||
(doom-hide-modeline-mode +1)))))
|
||||
(when doom-hide-modeline-mode
|
||||
(doom-hide-modeline-mode -1))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup|close-on-escape ()
|
||||
"If called inside a popup, try to close that popup window (see
|
||||
`+popup/close'). If called outside, try to close all popup windows (see
|
||||
`+popup/close-all')."
|
||||
(call-interactively
|
||||
(if (+popup-p)
|
||||
#'+popup/close
|
||||
#'+popup/close-all)))
|
||||
|
||||
|
||||
;;
|
||||
;; Commands
|
||||
;;
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'other-popup #'+popup/other)
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup/other ()
|
||||
"Cycle through popup windows, like `other-window'. Ignores regular windows."
|
||||
(interactive)
|
||||
(let ((popups (+popup-windows))
|
||||
(window (selected-window)))
|
||||
(unless popups
|
||||
(user-error "No popups are open"))
|
||||
(select-window (if (+popup-p)
|
||||
(or (car-safe (cdr (memq window popups)))
|
||||
(car (delq window popups))
|
||||
(car popups))
|
||||
(car popups)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup/close (&optional window force-p)
|
||||
"Close WINDOW, if it's a popup window.
|
||||
|
||||
This will do nothing if the popup's `escape-quit' window parameter is either nil
|
||||
or 'other. This window parameter is ignored if FORCE-P is non-nil."
|
||||
(interactive
|
||||
(list (selected-window)
|
||||
current-prefix-arg))
|
||||
(unless window
|
||||
(setq window (selected-window)))
|
||||
(when (and (+popup-p window)
|
||||
(or force-p
|
||||
(memq (+popup-parameter 'escape-quit window)
|
||||
'(t current))))
|
||||
(when +popup--remember-last
|
||||
(+popup--remember (list window)))
|
||||
(delete-window window)
|
||||
t))
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup/close-all (&optional force-p)
|
||||
"Close all open popup windows.
|
||||
|
||||
This will ignore popups with an `escape-quit' parameter that is either nil or
|
||||
'current. This window parameter is ignored if FORCE-P is non-nil."
|
||||
(interactive "P")
|
||||
(let (targets +popup--remember-last)
|
||||
(dolist (window (+popup-windows))
|
||||
(when (or force-p
|
||||
(memq (+popup-parameter 'escape-quit window)
|
||||
'(t other)))
|
||||
(push window targets)))
|
||||
(when targets
|
||||
(+popup--remember targets)
|
||||
(mapc #'delete-window targets)
|
||||
t)))
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup/toggle ()
|
||||
"If popups are open, close them. If they aren't, restore the last one or open
|
||||
the message buffer in a popup window."
|
||||
(interactive)
|
||||
(cond ((+popup-windows)
|
||||
(+popup/close-all))
|
||||
((ignore-errors (+popup/restore)))
|
||||
((display-buffer (get-buffer "*Messages*")))))
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup/restore ()
|
||||
"Restore the last popups that were closed, if any."
|
||||
(interactive)
|
||||
(unless +popup--last
|
||||
(error "No popups to restore"))
|
||||
(cl-loop for (buffer alist state) in +popup--last
|
||||
if (and (buffer-live-p buffer)
|
||||
(+popup-buffer buffer alist))
|
||||
do (window-state-put state it))
|
||||
(setq +popup--last nil))
|
||||
|
||||
;;;###autoload
|
||||
(defun +popup/raise ()
|
||||
"Raise the current popup window into a regular window."
|
||||
(interactive)
|
||||
(unless (+popup-p)
|
||||
(user-error "Cannot raise a non-popup window"))
|
||||
(let ((window (selected-window))
|
||||
(buffer (current-buffer))
|
||||
+popup--remember-last)
|
||||
(set-window-parameter window 'transient nil)
|
||||
(+popup/close window 'force)
|
||||
(display-buffer-pop-up-window buffer nil)))
|
||||
|
||||
|
||||
;;
|
||||
;; Macros
|
||||
;;
|
||||
|
||||
;;;###autoload
|
||||
(defmacro without-popups! (&rest body)
|
||||
"Run BODY with a default `display-buffer-alist', ignoring the popup rules set
|
||||
with the :popup setting."
|
||||
`(let ((display-buffer-alist +popup--old-display-buffer-alist))
|
||||
,@body))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro save-popups! (&rest body)
|
||||
"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 (+popup-p))
|
||||
(popups (+popup-windows))
|
||||
(popup-states
|
||||
(cl-loop for p in popups
|
||||
collect (cons (window-buffer p) (window-state-get p))))
|
||||
+popup--last)
|
||||
(dolist (p popups)
|
||||
(+popup/close p 'force))
|
||||
(unwind-protect
|
||||
(progn ,@body)
|
||||
(when popups
|
||||
(let ((origin (selected-window)))
|
||||
(+popup/restore)
|
||||
(unless in-popup-p
|
||||
(select-window origin)))))))
|
||||
|
196
modules/feature/popup/config.el
Normal file
196
modules/feature/popup/config.el
Normal file
|
@ -0,0 +1,196 @@
|
|||
;;; config.el -*- lexical-binding: t; -*-
|
||||
|
||||
(defconst +popup-window-parameters
|
||||
'(transient escape-quit select modeline alist)
|
||||
"A list of custom parameters to be added to `window-persistent-parameters'.
|
||||
Modifying this has no effect, unless done before feature/popup loads.
|
||||
|
||||
(transient . CDR)
|
||||
CDR can be t, an integer or nil. It represents the number of seconds before
|
||||
the buffer belonging to a closed popup window is killed.
|
||||
|
||||
If t, CDR will default to `+popup-ttl'.
|
||||
If 0, the buffer is immediately killed.
|
||||
If nil, the buffer won't be killed.
|
||||
|
||||
(escape-quit . CDR)
|
||||
CDR can be t, 'other, 'current or nil. This determines the behavior of the
|
||||
escape key in or outside of popup windows.
|
||||
|
||||
If t, close the popup if escape is pressed inside or outside of popups.
|
||||
If 'other, close this popup if escape is pressed outside of any popup. This is
|
||||
great for popups you just want to peek at and discard.
|
||||
If 'current, close the current popup if escape is pressed from inside of
|
||||
the popup.
|
||||
If nil, pressing escape will never close this buffer.
|
||||
|
||||
(select . BOOl)
|
||||
CDR is a boolean that determines whether to focus the popup window after it
|
||||
opens.
|
||||
|
||||
(modeline . CDR)
|
||||
CDR can be t (show the default modeline), a symbol representing the name of a
|
||||
modeline defined with `def-modeline!', or nil (show no modeline).
|
||||
|
||||
(alist . CDR)
|
||||
This is an internal parameter and should not be set or modified.
|
||||
|
||||
Since I can't find this information anywhere but the Emacs manual, I'll include
|
||||
a brief description of some native window parameters that Emacs uses:
|
||||
|
||||
(delete-window . CDR)
|
||||
(delete-other-window . CDR)
|
||||
(split-window . CDR)
|
||||
(other-window . CDR)
|
||||
This applies to all four of the above: CDR can be t or a function. If t, using
|
||||
those functions on this window will ignore all window parameters.
|
||||
|
||||
If CDR is a function, it will replace the native function when used on this
|
||||
window. e.g. if CDR is #'ignore (delete-window popup) will run (ignore popup)
|
||||
instead of deleting the window!
|
||||
(no-other-window . BOOL)
|
||||
If CDR is non-nil, this window becomes invisible to `other-window' and
|
||||
`pop-to-buffer'. Doom popups sets this. The default is nil.")
|
||||
|
||||
(defvar +popup-default-alist
|
||||
'((slot . 1)
|
||||
(window-height . 0.14)
|
||||
(window-width . 26)
|
||||
(reusable-frames . visible))
|
||||
"The default alist for `display-buffer-alist' rules.")
|
||||
|
||||
(defvar +popup-default-parameters
|
||||
'((transient . t)
|
||||
(escape-quit . t))
|
||||
"The default window parameters to add alists fed to `display-buffer-alist'.")
|
||||
|
||||
(defvar +popup-ttl 10
|
||||
"The default time-to-live for transient buffers whose popup buffers have been
|
||||
deleted.")
|
||||
|
||||
(defvar +popup-mode-map (make-sparse-keymap)
|
||||
"Active keymap in a session with the popup system enabled. See
|
||||
`+popup-mode'.")
|
||||
|
||||
(defvar +popup-buffer-mode-map (make-sparse-keymap)
|
||||
"Active keymap in popup windows. See `+popup-buffer-mode'.")
|
||||
|
||||
|
||||
(defvar +popup--display-buffer-alist nil)
|
||||
(defvar +popup--old-display-buffer-alist nil)
|
||||
(defvar +popup--remember-last t)
|
||||
(defvar +popup--last nil)
|
||||
(defvar-local +popup--timer nil)
|
||||
|
||||
|
||||
;;
|
||||
(def-setting! :popup (condition &optional alist parameters)
|
||||
"Register a popup rule.
|
||||
|
||||
CONDITION can be a regexp string or a function. See `display-buffer' for a list
|
||||
of possible entries for ALIST, which tells the display system how to initialize
|
||||
the popup window. PARAMETERS is an alist of window parameters. See
|
||||
`+popup-window-parameters' for a list of custom parameters provided by the popup
|
||||
module."
|
||||
`(let ((alist ,alist)
|
||||
(parameters ,parameters))
|
||||
,(when alist
|
||||
'(when-let* ((size (cdr (assq 'size alist))))
|
||||
(setq alist (assq-delete-all 'size alist))
|
||||
(push (cons (pcase (cdr (or (assq 'side alist)
|
||||
(assq 'side +popup-default-alist)))
|
||||
((or `left `right) 'window-width)
|
||||
(_ 'window-height))
|
||||
size)
|
||||
alist)))
|
||||
(prog1 (push (append (list ,condition '(+popup-buffer))
|
||||
alist
|
||||
(list (cons 'window-parameters parameters)))
|
||||
+popup--display-buffer-alist)
|
||||
(when (bound-and-true-p +popup-mode)
|
||||
(setq display-buffer-alist +popup--display-buffer-alist)))))
|
||||
|
||||
|
||||
;;
|
||||
;; Default popup rules & bootstrap
|
||||
;;
|
||||
|
||||
(eval-when-compile
|
||||
(set! :popup "^ \\*")
|
||||
(set! :popup "^\\*" nil '((select . t)))
|
||||
(set! :popup "^\\*\\(?:scratch\\|Messages\\)" nil '((transient)))
|
||||
(set! :popup "^\\*Help"
|
||||
'((window-height . 0.2))
|
||||
'((select . t)))
|
||||
(set! :+popup "^\\*doom:"
|
||||
'((window-height . 0.35))
|
||||
'((select . t) (escape-quit) (transient))))
|
||||
|
||||
(setq +popup--display-buffer-alist (eval-when-compile +popup--display-buffer-alist))
|
||||
(add-hook 'doom-init-ui-hook #'+popup-mode)
|
||||
|
||||
(add-hook '+popup-buffer-mode-hook #'+popup|adjust-fringes)
|
||||
(add-hook '+popup-buffer-mode-hook #'+popup|set-modeline)
|
||||
|
||||
|
||||
;;
|
||||
;; Hacks
|
||||
;;
|
||||
|
||||
(defun doom*ignore-window-parameters (orig-fn &rest args)
|
||||
"Allow *interactive* window moving commands to traverse popups."
|
||||
(cl-letf (((symbol-function #'windmove-find-other-window)
|
||||
(lambda (direction &optional window ignore sign wrap mini)
|
||||
(window-in-direction
|
||||
(pcase dir (`up 'above) (`down 'below) (_ dir))
|
||||
window (bound-and-true-p +popup-mode) arg windmove-wrap-around t))))
|
||||
(apply orig-fn args)))
|
||||
(advice-add #'windmove-up :around #'doom*ignore-window-parameters)
|
||||
(advice-add #'windmove-down :around #'doom*ignore-window-parameters)
|
||||
(advice-add #'windmove-left :around #'doom*ignore-window-parameters)
|
||||
(advice-add #'windmove-right :around #'doom*ignore-window-parameters)
|
||||
|
||||
|
||||
(after! help-mode
|
||||
(defun doom--switch-from-popup (location)
|
||||
(let (origin)
|
||||
(save-popups!
|
||||
(switch-to-buffer (car location) nil t)
|
||||
(if (not (cdr location))
|
||||
(message "Unable to find location in file")
|
||||
(goto-char (cdr location))
|
||||
(recenter)
|
||||
(setq origin (selected-window))))
|
||||
(+popup/close)
|
||||
(select-window origin)))
|
||||
|
||||
;; Help buffers use `pop-to-window' to decide where to open followed links,
|
||||
;; which can be unpredictable. It should *only* replace the original buffer we
|
||||
;; opened the popup from. To fix this these three button types need to be
|
||||
;; redefined to set aside the popup before following a link.
|
||||
(define-button-type 'help-function-def
|
||||
:supertype 'help-xref
|
||||
'help-function
|
||||
(lambda (fun file)
|
||||
(require 'find-func)
|
||||
(when (eq file 'C-source)
|
||||
(setq file (help-C-file-name (indirect-function fun) 'fun)))
|
||||
(doom--switch-from-popup (find-function-search-for-symbol fun nil file))))
|
||||
|
||||
(define-button-type 'help-variable-def
|
||||
:supertype 'help-xref
|
||||
'help-function
|
||||
(lambda (var &optional file)
|
||||
(when (eq file 'C-source)
|
||||
(setq file (help-C-file-name var 'var)))
|
||||
(doom--switch-from-popup (find-variable-noselect var file))))
|
||||
|
||||
(define-button-type 'help-face-def
|
||||
:supertype 'help-xref
|
||||
'help-function
|
||||
(lambda (fun file)
|
||||
(require 'find-func)
|
||||
(doom--switch-from-popup (find-function-search-for-symbol fun 'defface file)))))
|
||||
|
||||
(provide 'config)
|
||||
;;; config.el ends here
|
|
@ -24,7 +24,7 @@
|
|||
(git-gutter-mode +1)))
|
||||
(add-hook! (text-mode prog-mode conf-mode) #'+version-control|git-gutter-maybe)
|
||||
:config
|
||||
(set! :popup "^\\*git-gutter.+\\*$" :regexp t :size 15 :noselect t)
|
||||
(set! :popup "^\\*git-gutter" nil '((select)))
|
||||
|
||||
;; Update git-gutter on focus (in case I was using git externally)
|
||||
(add-hook 'focus-in-hook #'git-gutter:update-all-windows)
|
||||
|
|
|
@ -11,10 +11,8 @@
|
|||
|
||||
|
||||
(after! vc-annotate
|
||||
(set! :popup
|
||||
'("*vc-diff*" :size 15 :noselect t)
|
||||
'("*vc-change-log*" :size 15)
|
||||
'(vc-annotate-mode :same t))
|
||||
(set! :popup "^\\vc-d" nil '((select))) ; *vc-diff*
|
||||
(set! :popup "^\\vc-c" nil '((select . t))) ; *vc-change-log*
|
||||
|
||||
(set! :evil-state 'vc-annotate-mode 'normal)
|
||||
(set! :evil-state 'vc-git-log-view-mode 'normal))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue