diff --git a/core/core-eval.el b/core/core-eval.el index 5386a78dc..fe1c64f0a 100644 --- a/core/core-eval.el +++ b/core/core-eval.el @@ -18,17 +18,25 @@ quickrun-replace-region helm-quickrun) :init (add-hook 'quickrun/mode-hook 'linum-mode) - :config (setq quickrun-focus-p nil)) + :config + (setq quickrun-focus-p nil) + (def-popup! "*quickrun*" :align below :size 10) + (def-popup! "*eval*" :align below :size 20)) (use-package repl-toggle :commands (rtog/toggle-repl rtog/add-repl) + :preface (defvar rtog/mode-repl-alist nil) :init - (defvar doom--repl-buffer nil "The current REPL buffer.") - (defvar-local repl-p nil "Whether this is a repl buffer or not.") - (setq rtog/mode-repl-alist '()) + (defvar doom-repl-buffer nil "The current REPL buffer.") (add-hook! repl-toggle-mode (evil-initialize-state 'emacs)) - :config + (def-popup! + (:custom (lambda (b &rest _) + (when (and (featurep 'repl-toggle) + (string-prefix-p "*" (buffer-name (get-buffer b)))) + (with-current-buffer b repl-toggle-mode)))) + :popup t :align below :size 16 :select t) + (map! :map repl-toggle-mode-map :ei "C-n" 'comint-next-input :ei "C-p" 'comint-previous-input @@ -57,6 +65,10 @@ :m "B" 'realgud:cmd-clear :n "c" 'realgud:cmd-continue) + ;; Popup rules + (def-popup! "\\`\\*\\(g\\|zsh\\|bash\\)db.*?\\*\\'" :size 20 :regexp t) + (def-popup! "\\`\\*trepanjs.*?\\*\\'" :size 20 :regexp t) + ;; Temporary Ex commands for the debugger (def-tmp-excmd! doom:def-debug-on doom:def-debug-off ("n[ext]" . realgud:cmd-next) diff --git a/core/core-evil.el b/core/core-evil.el index d456c7aa1..668053315 100644 --- a/core/core-evil.el +++ b/core/core-evil.el @@ -65,8 +65,11 @@ (Man-mode . emacs) (grep-mode . emacs))) - (map! :map evil-command-window-mode-map :n [escape] 'kill-buffer-and-window) + ;; Popups + (def-popup! "*evil-registers*" :align below :size 0.3) + (def-popup! "*Command Line*" :align below :size 8 :select t) + ;; Evil hacks (progn ; evil hacks (advice-add 'evil-force-normal-state :after 'doom*evil-esc-quit) (defun doom*evil-esc-quit () diff --git a/core/core-flycheck.el b/core/core-flycheck.el index 0758acd6e..4dbf350c7 100644 --- a/core/core-flycheck.el +++ b/core/core-flycheck.el @@ -9,6 +9,8 @@ flycheck-disabled-checkers '(emacs-lisp emacs-lisp-checkdoc make)) :config + (def-popup! " ?\\*Flycheck.+\\*" :align below :size 14 :noselect t :regexp t) + (unless (> emacs-major-version 24) ;; Fixes Unknown defun property `interactive-only' error (in emacs <25) by compiling ;; flycheck source files diff --git a/core/core-helm.el b/core/core-helm.el index b6fd9a9e0..d9cd9041e 100644 --- a/core/core-helm.el +++ b/core/core-helm.el @@ -43,6 +43,9 @@ :map helm-generic-files-map :e "ESC" 'helm-keyboard-quit) + ;;; Popup setup + (def-popup! "\\` ?\\*[hH]elm.*?\\*\\'" :align below :size 14 :select t :regexp t) + ;;; Helm hacks (defconst doom-helm-header-fg (face-attribute 'helm-source-header :foreground)) ;; Shrink source headers if there is only one source diff --git a/core/core-popup.el b/core/core-popup.el index 501a33d5c..eca9074bb 100644 --- a/core/core-popup.el +++ b/core/core-popup.el @@ -10,67 +10,32 @@ :config (shackle-mode 1) (setq shackle-rules - `(;; Debuggers - ("\\`\\*\\(g\\|zsh\\|bash\\)db.*?\\*\\'" :align below :size 20 :regexp t) - ("\\`\\*trepanjs.*?\\*\\'" :align below :size 20 :regexp t) - ("\\`\\*\\(debug:\\)haskell\\*\\'" :align below :size 20 :regexp t) - ;; Plugins - ("\\` ?\\*[hH]elm.*?\\*\\'" :align below :size 14 :select t :regexp t) - (" ?\\*Flycheck.+\\*" :align below :size 14 :noselect t :regexp t) - ("*helm bookmarks*" :align below :size 7 :select t) - (" *NeoTree*" :align left :select t) - ("*evil-registers*" :align below :size 0.3) - ("*quickrun*" :align below :size 10) - ("*nosetests*" :align below :size 0.4 :noselect t) - ("*esup*" :align below :size 30 :noselect t) - ("*ert*" :align below :size 20 :noselect t) - (eww-mode :align below :size 30 :select t) - ;; vcs - ("*git-messenger*" :align left :size 55 :select t) - ("^\\*git-gutter.+\\*$" :align below :size 15 :noselect t :regexp t) - ("*vc-diff*" :align below :size 15 :noselect t) - ("*vc-change-log*" :align below :size 15 :select t) - (vc-annotate-mode :same t) - ((:custom (lambda (b &rest _) (derived-mode-p 'magit-mode))) - :align below :size 0.5) - ;; Util - ("*Apropos*" :align below :size 0.3) - ("*minor-modes*" :align below :size 0.5 :noselect t) - ;; Org - (" *Agenda Commands*" :align below :size 30) - (" *Org todo*" :align below :size 5 :noselect t) - ("*Calendar*" :align below :size 0.4) - ("*Org Links*" :align below :size 5) - ("^\\*Org Agenda.+" :align below :size 0.4 :regexp t) - ("^\\*Org Src .+\\*$" :align below :size 0.4 :select t :regexp t) - ("^\\*Org-Babel.*\\*$" :align below :size 0.4 :regexp t) - ;; Emacs - (,doom-buffer-name :align below :size 0.3 :select t) - ("*Completions*" :align below :size 20 :noselect t) - ("*Help*" :align below :size 16 :select t) - ("*Messages*" :align below :size 15 :select t) - ("*Warnings*" :align below :size 10 :noselect t) - ("*processing-compilation*" :align below :size 10 :noselect t) + `(;; Util ("^\\*.+-Profiler-Report .+\\*$" :align below :size 0.3 :regexp t) - (compilation-mode :align below :size 15 :noselect t) - ("*Backtrace*" :align below :size 25 :noselect t) - ;; Custom + REPLs - ("*eval*" :align below :size 20) - ("^\\*doom.+\\*$" :regexp t :align below :size 12 :noselect t) - ((:custom (lambda (b &rest _) - (when (featurep 'repl-toggle) - (when (string-prefix-p "*" (buffer-name (get-buffer b))) - (with-current-buffer b repl-toggle-mode))))) - :popup t :align below :size 16 :select t))) + ("*esup*" :align below :size 30 :noselect t) + ("*minor-modes*" :align below :size 0.5 :noselect t) + ;; Emacs + ("*Apropos*" :align below :size 0.3) + ("*Backtrace*" :align below :size 25 :noselect t) + ("*Completions*" :align below :size 20 :noselect t) + ("*Help*" :align below :size 16 :select t) + ("*Messages*" :align below :size 15 :select t) + ("*Warnings*" :align below :size 10 :noselect t) + (compilation-mode :align below :size 15 :noselect t) + (eww-mode :align below :size 30 :select t) + ;; vcs + ("*vc-diff*" :align below :size 15 :noselect t) + ("*vc-change-log*" :align below :size 15 :select t) + (vc-annotate-mode :same t))) (defvar doom-popup-windows '() "A list of windows that have been opened via shackle. Do not touch this!") - (defvar-local doom-popup-protect nil - "If non-nil, this popup buffer won't be killed when closed.") (defvar doom-last-popup nil "The last (important) popup buffer.") (defvar doom-prev-buffer nil "The buffer from which the popup was invoked.") + (defvar-local doom-popup-protect nil + "If non-nil, this popup buffer won't be killed when closed.") (defvar doom-popup-inescapable-modes '(compilation-mode comint-mode) @@ -97,7 +62,7 @@ ;; Hacks ;; -(defun doom-load-magit-hacks () +(defun doom-popup-magit-hacks () ;; Some wrassling must be done to get magit to kill itself, and trigger my ;; shackle popup hooks. (setq magit-bury-buffer-function @@ -112,11 +77,34 @@ (select-window (get-buffer-window doom-prev-buffer))) (switch-to-buffer b)))) +(after! evil + (defun doom*evil-command-window (orig-fn &rest args) + (cl-flet ((switch-to-buffer ())) + (apply orig-fn args)) + ) + (defun doom*evil-command-window (hist cmd-key execute-fn) + (when (eq major-mode 'evil-command-window-mode) + (user-error "Cannot recursively open command line window")) + (dolist (win (window-list)) + (when (equal (buffer-name (window-buffer win)) + "*Command Line*") + (kill-buffer (window-buffer win)) + (delete-window win))) + (setq evil-command-window-current-buffer (current-buffer)) + (ignore-errors (kill-buffer "*Command Line*")) + (with-current-buffer (pop-to-buffer "*Command Line*") + (setq-local evil-command-window-execute-fn execute-fn) + (setq-local evil-command-window-cmd-key cmd-key) + (evil-command-window-mode) + (evil-command-window-insert-commands hist) + (doom|hide-mode-line))) + (advice-add 'evil-command-window :override 'doom*evil-command-window)) + (after! help-mode - ;; So that help buffer links do not open in the help popup, we need to redefine these - ;; three button types to use `switch-to-buffer' rather than `pop-to-buffer'. - ;; Instead of lambas these help-functions should be function symbols, so that - ;; we could advise those instead of clumsify redefine these button types. + ;; So that file links in help buffers don't replace the help buffer, we need + ;; to redefine these three button types to use `doom/popup-save' and + ;; `switch-to-buffer' rather than `pop-to-buffer'. This way, it is sure to + ;; open links in the source buffer. (define-button-type 'help-function-def :supertype 'help-xref 'help-function (lambda (fun file) @@ -159,18 +147,18 @@ 'help-echo (purecopy "mouse-2, RET: find face's definition"))) (after! helm - ;; This is a good alternative to either popwin or shackle, specifically for helm. If - ;; either fail me (for the last time), this is where I'll turn. + ;; This is a good alternative to either popwin or shackle, specifically for + ;; helm. If either fail me (for the last time), this is where I'll turn. ;;(add-to-list 'display-buffer-alist ;; `(,(rx bos "*helm" (* not-newline) "*" eos) ;; (display-buffer-in-side-window) ;; (inhibit-same-window . t) ;; (window-height . 0.4))) - ;; Helm tries to clean up after itself, but shackle has already done this. This fixes - ;; that. To reproduce, add a helm rule in `shackle-rules', open two splits - ;; side-by-side, move to the buffer on the right and invoke helm. It will close all - ;; but the left-most buffer. + ;; Helm tries to clean up after itself, but shackle has already done this. + ;; This fixes that. To reproduce, add a helm rule in `shackle-rules', open two + ;; splits side-by-side, move to the buffer on the right and invoke helm. It + ;; will close all but the left-most buffer. (setq-default helm-reuse-last-window-split-state t helm-split-window-in-side-p t)) @@ -178,8 +166,7 @@ (setq helm-swoop-split-window-function (lambda (b) (doom/popup-buffer b)))) (after! helm-ag - ;; Helm-ag needs a little coaxing for it to cooperate with shackle. Mostly to prevent - ;; it from switching between windows and buffers. + ;; This prevents helm-ag from switching between windows and buffers. (defadvice helm-ag--edit-abort (around helm-ag-edit-abort-popup-compat activate) (cl-letf (((symbol-function 'select-window) 'ignore)) ad-do-it) (doom/popup-close nil t t)) @@ -192,8 +179,7 @@ ad-do-it))) (after! quickrun - ;; This allows us to run code several times in a row without having to close - ;; the popup window and move back to the code buffer. + ;; This allows us to rerun code from inside a quickrun buffer. (defun doom*quickrun-close-popup (&optional _ _ _ _) (let* ((buffer (get-buffer quickrun/buffer-name)) (window (and buffer (get-buffer-window buffer)))) @@ -203,20 +189,19 @@ (advice-add 'quickrun :before 'doom*quickrun-close-popup) (advice-add 'quickrun-region :before 'doom*quickrun-close-popup) - ;; Turns on `nlinum-mode', and ensures window is scrolled to EOF + ;; Ensures window is scrolled to BOF (defun doom|quickrun-after-run () - (let ((window (get-buffer-window quickrun/buffer-name))) - (with-selected-window window - (goto-char (point-min))))) + (with-selected-window (get-buffer-window quickrun/buffer-name) + (goto-char (point-min)))) (add-hook 'quickrun-after-run-hook 'doom|quickrun-after-run) (add-hook 'quickrun/mode-hook 'doom|hide-mode-line)) (add-hook! org-load - ;; This ensures org-src-edit yields control of its buffer to shackle. + ;; Ensures org-src-edit yields control of its buffer to shackle. (defun org-src-switch-to-buffer (buffer context) (pop-to-buffer buffer)) - ;; And these for org-todo, org-link and agenda + ;; And these for org-todo, org-link and org-agenda (defun org-pop-to-buffer-same-window (&optional buffer-or-name norecord label) "Pop to buffer specified by BUFFER-OR-NAME in the selected window." (display-buffer buffer-or-name)) diff --git a/core/core-scratch.el b/core/core-scratch.el index d698586ab..01174fc79 100644 --- a/core/core-scratch.el +++ b/core/core-scratch.el @@ -13,6 +13,9 @@ (defvar-local doom-buffer-edited nil "If non-nil, the scratch buffer has been edited.") +(def-popup! doom-buffer-name :align below :size 0.3 :select t) +(def-popup! "^\\*doom.+\\*$" :regexp t :align below :size 12 :noselect t) + (define-derived-mode doom-mode text-mode "DOOM" "Major mode for special DOOM buffers.") diff --git a/core/core-vcs.el b/core/core-vcs.el index 67bb2fb4e..e3453ca0d 100644 --- a/core/core-vcs.el +++ b/core/core-vcs.el @@ -16,6 +16,7 @@ (add-hook! (text-mode prog-mode conf-mode) 'git-gutter-mode) :config (require 'git-gutter-fringe) + (def-popup! "^\\*git-gutter.+\\*$" :align below :size 15 :noselect t :regexp t) (define-fringe-bitmap 'git-gutter-fr:added [224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224 224] @@ -41,6 +42,7 @@ :commands git-messenger:popup-message :init (defvar git-messenger-map (make-sparse-keymap)) :config + (def-popup! "*git-messenger*" :align left :size 55 :select t) (setq git-messenger:show-detail t) (map! :map git-messenger-map "" 'git-messenger:popup-close @@ -49,7 +51,9 @@ (use-package magit :commands (magit-status) :config - (doom-load-magit-hacks) + (doom-popup-magit-hacks) + (def-popup! (:custom (lambda (b &rest _) (derived-mode-p 'magit-mode))) + :align below :size 0.5) (add-hook 'magit-mode-hook 'turn-off-evil-snipe-override-mode)) (use-package evil-magit :after magit diff --git a/core/defuns/defuns-popups.el b/core/defuns/defuns-popups.el index d98dad24c..d867d538a 100644 --- a/core/defuns/defuns-popups.el +++ b/core/defuns/defuns-popups.el @@ -10,11 +10,10 @@ (defun doom/popup-p (&optional window) "Whether WINDOW is a shackle popup window or not." (and doom-popup-windows - (-any? (lambda (w) - (if (window-live-p w) t (doom/popup-remove w) nil)) - doom-popup-windows) + (--any? (if (window-live-p it) t (doom/popup-remove it) nil) + doom-popup-windows) (if window - (-any? (lambda (w) (eq window w)) doom-popup-windows) + (--any? (eq window it) doom-popup-windows) t))) ;;;###autoload @@ -122,5 +121,10 @@ (setq-local doom-popup-protect t) (setq doom-last-popup (current-buffer)))))) +;;;###autoload +(defun doom*save-popup (orig-fun &rest args) + "Prevents messing up a popup buffer on window changes" + (doom/popup-save (apply orig-fun args))) + (provide 'defuns-popups) ;;; defuns-popups.el ends here diff --git a/core/defuns/defuns-repl.el b/core/defuns/defuns-repl.el index eb2fac2a4..fdd81e35b 100644 --- a/core/defuns/defuns-repl.el +++ b/core/defuns/defuns-repl.el @@ -4,12 +4,12 @@ (evil-define-command doom:repl (&optional bang command) :repeat nil (interactive "") - (if (and doom--repl-buffer (buffer-live-p doom--repl-buffer)) - (doom/popup-buffer doom--repl-buffer) + (if (and doom-repl-buffer (buffer-live-p doom-repl-buffer)) + (doom/popup-buffer doom-repl-buffer) (rtog/toggle-repl (if (use-region-p) 4)) - (setq doom--repl-buffer (current-buffer)) + (setq doom-repl-buffer (current-buffer)) (when command - (with-current-buffer doom--repl-buffer + (with-current-buffer doom-repl-buffer (insert command) (unless bang (comint-send-input)))))) @@ -22,12 +22,12 @@ (selection (s-trim (buffer-substring-no-properties beg end)))) (doom:repl bang) (when (and region-p beg end) - (let* ((buf doom--repl-buffer) + (let* ((buf doom-repl-buffer) (win (get-buffer-window buf))) (unless (eq buf (doom/popup-p (get-buffer-window buf))) (doom/popup-buffer buf)) - (when (and doom--repl-buffer (buffer-live-p doom--repl-buffer)) - (with-current-buffer doom--repl-buffer + (when (and doom-repl-buffer (buffer-live-p doom-repl-buffer)) + (with-current-buffer doom-repl-buffer (goto-char (point-max)) (insert selection))))))) diff --git a/core/defuns/macros-popups.el b/core/defuns/macros-popups.el new file mode 100644 index 000000000..e68ed812b --- /dev/null +++ b/core/defuns/macros-popups.el @@ -0,0 +1,8 @@ +;;; macros-popups.el + +;;;###autoload +(defmacro def-popup! (&rest params) + `(push ',params shackle-rules)) + +(provide 'macros-popups) +;;; macros-popups.el ends here diff --git a/init.el b/init.el index a79838c04..ea1998671 100644 --- a/init.el +++ b/init.el @@ -36,6 +36,7 @@ :default-font ("Fira Mono" 12) ;;; The heart of DOOM + core-popup ; taming sudden and inevitable windows core-os ; os-specific config core-scratch ; a perdier scratch buffer core-ui ; draw me like one of your French editors @@ -50,7 +51,6 @@ core-helm ; a search engine for life and love core-workgroups ; cure Emacs alzheimers + tab emulation core-eval ; run code, run; debug too - core-popup ; taming sudden and inevitable windows ;;; Dev environments module-cc ; C/C++/Obj-C madness diff --git a/modules/module-db.el b/modules/module-db.el index eab8e0cc3..deba01e47 100644 --- a/modules/module-db.el +++ b/modules/module-db.el @@ -3,6 +3,7 @@ (use-package sql-mode :mode "\\.sql$" :config + (def-popup! "\\*SQL.*\\*" :align below :size 0.4 :noselect t :regexp t) (evil-set-initial-state 'sql-interactive-mode 'emacs) (push 'sql-interactive-mode doom-popup-protect-modes) ;; For my local development environment diff --git a/modules/module-elisp.el b/modules/module-elisp.el index 7e421d84d..56faa5f60 100644 --- a/modules/module-elisp.el +++ b/modules/module-elisp.el @@ -19,6 +19,8 @@ ("advice-add" "advice-remove") ("add-hook" "add-hook!" "remove-hook"))) + (def-popup! "*ert*" :align below :size 20 :noselect t) + ;; Don't affect lisp indentation (only `tab-width') (setq editorconfig-indentation-alist (delq (assq 'emacs-lisp-mode editorconfig-indentation-alist) @@ -38,7 +40,7 @@ "(\\(def-" (regexp-opt '("electric" "project-type" "company-backend" "builder" "repl" "text-obj" "tmp-excmd" "rotate" - "repeat" "yas-mode" "version-cmd" "docset" + "repeat" "yas-mode" "version-cmd" "docset" "popup" "open-with")) "!\\)") (1 font-lock-keyword-face append)) diff --git a/modules/module-eshell.el b/modules/module-eshell.el index 487fed4ad..bc790d29d 100644 --- a/modules/module-eshell.el +++ b/modules/module-eshell.el @@ -16,6 +16,9 @@ ;; em-alias eshell-aliases-file (concat doom-temp-dir "/.eshell-aliases")) + :config + (def-popup! eshell-mode :frame t :select t) + ;; plan 9 smart shell (require 'em-smart) (add-to-list 'eshell-modules-list 'eshell-smart) diff --git a/modules/module-haskell.el b/modules/module-haskell.el index c63cbcdf8..95c530fbc 100644 --- a/modules/module-haskell.el +++ b/modules/module-haskell.el @@ -9,6 +9,7 @@ :init (add-hook! haskell-mode '(interactive-haskell-mode flycheck-mode)) :config + (def-popup! "*debug:haskell*" :size 20) (def-repl! haskell-mode switch-to-haskell) (push ".hi" completion-ignored-extensions)) diff --git a/modules/module-org.el b/modules/module-org.el index a33503846..597d87c44 100644 --- a/modules/module-org.el +++ b/modules/module-org.el @@ -37,6 +37,14 @@ (add-hook 'evil-insert-state-exit-hook 'doom|org-update nil t)) (defun doom|org-init () + (def-popup! " *Agenda Commands*" :align below :size 30) + (def-popup! " *Org todo*" :align below :size 5 :noselect t) + (def-popup! "*Calendar*" :align below :size 0.4) + (def-popup! "*Org Links*" :align below :size 5) + (def-popup! "^\\*Org Agenda.+" :align below :size 0.4 :regexp t) + (def-popup! "^\\*Org Src .+\\*$" :align below :size 0.4 :select t :regexp t) + (def-popup! "^\\*Org-Babel.*\\*$" :align below :size 0.4 :regexp t) + (setq-default org-export-coding-system 'utf-8 diff --git a/modules/module-processing.el b/modules/module-processing.el index 1ee75fadb..5e065a671 100644 --- a/modules/module-processing.el +++ b/modules/module-processing.el @@ -9,6 +9,7 @@ :config (def-builder! processing-mode processing-sketch-build) + (def-popup! "*processing-compilation*" :align below :size 10 :noselect t) (setq processing-location "/usr/local/bin/processing-java" processing-application-dir "/Applications/Processing.app" processing-sketchbook-dir "~/Dropbox/work/pde" diff --git a/modules/module-python.el b/modules/module-python.el index 6ab8664b2..0963b54e2 100644 --- a/modules/module-python.el +++ b/modules/module-python.el @@ -67,6 +67,7 @@ :preface (defvar nose-mode-map (make-sparse-keymap)) :init (associate! nose-mode :match "/test_.+\\.py$" :in (python-mode)) :config + (def-popup! "*nosetests*" :align below :size 0.4 :noselect t) (def-yas-mode! 'nose-mode) (map! :map nose-mode-map (:localleader