diff --git a/core/core-ui.el b/core/core-ui.el index d55f455c6..a6292cd8a 100644 --- a/core/core-ui.el +++ b/core/core-ui.el @@ -544,6 +544,23 @@ frame's window-system, the theme will be reloaded.") ;; line numbers in most modes (add-hook! (prog-mode text-mode conf-mode) #'doom|enable-line-numbers) +;; ensure posframe cleans up after itself +(after! posframe + ;; TODO Find a better place for this + (defun doom|delete-posframe-on-escape () + "TODO" + (unless (frame-parameter (selected-frame) 'posframe-buffer) + (cl-loop for frame in (frame-list) + if (and (frame-parameter frame 'posframe-buffer) + (not (frame-visible-p frame))) + do (delete-frame frame)) + (dolist (buffer (buffer-list)) + (let ((frame (buffer-local-value 'posframe--frame buffer))) + (when (and frame (or (not (frame-live-p frame)) + (not (frame-visible-p frame)))) + (posframe--kill-buffer buffer)))))) + (add-hook 'doom-escape-hook #'doom|delete-posframe-on-escape) + (add-hook 'doom-cleanup-hook #'posframe-delete-all)) ;; Customized confirmation prompt for quitting Emacs (defun doom-quit-p (&optional prompt) diff --git a/init.example.el b/init.example.el index e57336bc1..dd96126fd 100644 --- a/init.example.el +++ b/init.example.el @@ -22,10 +22,11 @@ :completion (company ; the ultimate code completion backend +auto ; as-you-type code completion - +childframe) ; a nicer company UI. Emacs +26 only! + +childframe) ; a nicer company UI (Emacs 26+ only) ;helm ; the *other* search engine for love and life ;ido ; the other *other* search engine... - ivy ; a search engine for love and life + (ivy ; a search engine for love and life + +childframe) ; uses childframes for popups (Emacs 26+ only) :ui doom ; what makes DOOM look the way it does @@ -35,7 +36,6 @@ evil-goggles ; display visual hints when editing in evil hl-todo ; highlight TODO/FIXME/NOTE tags nav-flash ; blink the current line after jumping - ;posframe ; use child frames where possible (Emacs 26+ only) ;tabbar ; FIXME an (incomplete) tab bar for Emacs ;unicode ; extended unicode support for various languages vi-tilde-fringe ; fringe tildes to mark beyond EOB diff --git a/modules/completion/ivy/autoload/posframe.el b/modules/completion/ivy/autoload/posframe.el new file mode 100644 index 000000000..43f034abc --- /dev/null +++ b/modules/completion/ivy/autoload/posframe.el @@ -0,0 +1,16 @@ +;;; completion/ivy/autoload/posframe.el -*- lexical-binding: t; -*- +;;;###if (featurep! +childframe) + +;;;###autoload +(defun +ivy-display-at-frame-center-near-bottom (str) + "TODO" + (ivy-posframe--display str #'+ivy-poshandler-frame-center-near-bottom)) + +;;;###autoload +(defun +ivy-poshandler-frame-center-near-bottom (info) + "TODO" + (let ((parent-frame (plist-get info :parent-frame)) + (pos (posframe-poshandler-frame-center info))) + (cons (car pos) + (truncate (/ (frame-pixel-height parent-frame) 1.6))))) + diff --git a/modules/completion/ivy/config.el b/modules/completion/ivy/config.el index e6b2fa3cf..9259fdb85 100644 --- a/modules/completion/ivy/config.el +++ b/modules/completion/ivy/config.el @@ -187,3 +187,37 @@ immediately runs it on the current candidate (ending the ivy session)." (def-package! wgrep :commands (wgrep-setup wgrep-change-to-wgrep-mode) :config (setq wgrep-auto-save-buffer t)) + + +(def-package! ivy-posframe + :when EMACS26+ + :when (featurep! +childframe) + :hook (ivy-mode . ivy-posframe-enable) + :preface + ;; This function searches the entire `obarray' just to populate + ;; `ivy-display-functions-props'. There are 15k entries in mine! This is + ;; wasteful, so... + (advice-add #'ivy-posframe-setup :override #'ignore) + :config + ;; ... let's do it manually + (dolist (fn (list 'ivy-posframe-display-at-frame-bottom-left + 'ivy-posframe-display-at-frame-center + 'ivy-posframe-display-at-point + 'ivy-posframe-display-at-frame-bottom-window-center + 'ivy-posframe-display + 'ivy-posframe-display-at-window-bottom-left + 'ivy-posframe-display-at-window-center + '+ivy-display-at-frame-center-near-bottom)) + (push (list fn :cleanup 'ivy-posframe-cleanup) ivy-display-functions-props)) + + (push '(t . +ivy-display-at-frame-center-near-bottom) ivy-display-functions-alist) + + ;; posframe doesn't work well with async sources + (dolist (fn '(swiper counsel-rg counsel-ag counsel-pt counsel-grep counsel-git-grep)) + (push (cons fn nil) ivy-display-functions-alist)) + + (setq ivy-height 16 + ivy-fixed-height-minibuffer nil + ivy-posframe-parameters `((min-width . 90) + (min-height . ,ivy-height) + (internal-border-width . 10)))) diff --git a/modules/completion/ivy/doctor.el b/modules/completion/ivy/doctor.el new file mode 100644 index 000000000..21300e86d --- /dev/null +++ b/modules/completion/ivy/doctor.el @@ -0,0 +1,4 @@ +;;; completion/ivy/doctor.el -*- lexical-binding: t; -*- + +(when (and (not EMACS26+) (featurep! +childframe)) + (error! "The +childframe feature requires Emacs 26+")) diff --git a/modules/completion/ivy/packages.el b/modules/completion/ivy/packages.el index fab27d27e..0d764a54d 100644 --- a/modules/completion/ivy/packages.el +++ b/modules/completion/ivy/packages.el @@ -9,3 +9,6 @@ (package! ivy-hydra) (package! ivy-rich) (package! wgrep) + +(when (and EMACS26+ (featurep! +childframe)) + (package! ivy-posframe)) diff --git a/modules/ui/posframe/autoload.el b/modules/ui/posframe/autoload.el deleted file mode 100644 index 74e8625c0..000000000 --- a/modules/ui/posframe/autoload.el +++ /dev/null @@ -1,28 +0,0 @@ -;;; ui/posframe/autoloads.el -*- lexical-binding: t; -*- - -;;;###autoload -(defun +posframe-ivy-display-at-frame-center-near-bottom (str) - "TODO" - (ivy-posframe--display str #'+posframe-poshandler-frame-center-near-bottom)) - -;;;###autoload -(defun +posframe-poshandler-frame-center-near-bottom (info) - "TODO" - (let ((parent-frame (plist-get info :parent-frame)) - (pos (posframe-poshandler-frame-center info))) - (cons (car pos) - (truncate (/ (frame-pixel-height parent-frame) 1.6))))) - -;;;###autoload -(defun +posframe|delete-on-escape () - "TODO" - (unless (frame-parameter (selected-frame) 'posframe-buffer) - (cl-loop for frame in (frame-list) - if (and (frame-parameter frame 'posframe-buffer) - (not (frame-visible-p frame))) - do (delete-frame frame)) - (dolist (buffer (buffer-list)) - (let ((frame (buffer-local-value 'posframe--frame buffer))) - (when (and frame (or (not (frame-live-p frame)) - (not (frame-visible-p frame)))) - (posframe--kill-buffer buffer)))))) diff --git a/modules/ui/posframe/config.el b/modules/ui/posframe/config.el deleted file mode 100644 index 5dd7af23d..000000000 --- a/modules/ui/posframe/config.el +++ /dev/null @@ -1,42 +0,0 @@ -;;; ui/posframe/config.el -*- lexical-binding: t; -*- - -(def-package! posframe - :defer t - :config - (add-hook 'doom-cleanup-hook #'posframe-delete-all) - (add-hook 'doom-escape-hook #'+posframe|delete-on-escape)) - - -(def-package! ivy-posframe - :when EMACS26+ - :hook (ivy-mode . ivy-posframe-enable) - :preface - ;; This function searches the entire `obarray' just to populate - ;; `ivy-display-functions-props'. There are 15k entries in mine! This is - ;; wasteful, so... - (advice-add #'ivy-posframe-setup :override #'ignore) - :config - ;; ... let's do it manually - (dolist (fn (list 'ivy-posframe-display-at-frame-bottom-left - 'ivy-posframe-display-at-frame-center - 'ivy-posframe-display-at-point - 'ivy-posframe-display-at-frame-bottom-window-center - 'ivy-posframe-display - 'ivy-posframe-display-at-window-bottom-left - 'ivy-posframe-display-at-window-center - '+posframe-ivy-display-at-frame-center-near-bottom)) - (push (list fn :cleanup 'ivy-posframe-cleanup) ivy-display-functions-props)) - - (push '(t . +posframe-ivy-display-at-frame-center-near-bottom) ivy-display-functions-alist) - - ;; posframe doesn't work well with async sources - (dolist (fn '(swiper counsel-rg counsel-ag counsel-pt counsel-grep counsel-git-grep)) - (push (cons fn nil) ivy-display-functions-alist)) - - (setq ivy-height 16 - ivy-fixed-height-minibuffer nil - ivy-posframe-parameters `((min-width . 90) - (min-height . ,ivy-height) - (internal-border-width . 10)))) - -;; TODO helm-posframe? diff --git a/modules/ui/posframe/doctor.el b/modules/ui/posframe/doctor.el deleted file mode 100644 index e43fa4e9f..000000000 --- a/modules/ui/posframe/doctor.el +++ /dev/null @@ -1,5 +0,0 @@ -;; -*- lexical-binding: t; no-byte-compile: t; -*- -;;; ui/posframe/doctor.el - -(unless EMACS26+ - (error! "This module doesn't work in Emacs %s (minimum: Emacs 26)" emacs-version)) diff --git a/modules/ui/posframe/packages.el b/modules/ui/posframe/packages.el deleted file mode 100644 index b5013939f..000000000 --- a/modules/ui/posframe/packages.el +++ /dev/null @@ -1,6 +0,0 @@ -;; -*- no-byte-compile: t; -*- -;;; ui/posframe/packages.el - -(when EMACS26+ - (when (featurep! :completion ivy) - (package! ivy-posframe)))