Skip to content

Commit

Permalink
Toggle fixes when purpose-mode is toggled (#180)
Browse files Browse the repository at this point in the history
* Toggle fixes when purpose-mode is toggled

Toggle the integration fixes on when purpose-mode is activated, and toggle them
off when purpose-mode is deactivated. Mainly, this means the relevant advices
are now active only while purpose-mode is active.
  • Loading branch information
bmag committed Mar 9, 2021
1 parent 1a41373 commit 655df54
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 22 deletions.
85 changes: 65 additions & 20 deletions window-purpose-fixes.el
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,43 @@
(require 'window-purpose-switch)
(require 'window-purpose-configuration)

(defvar purpose-fix-togglers-hook nil
"List of functions that toggle fixes.
Each function in the list is responsible to toggle a fix. Each
function should take no argument, and enable its fix if
`purpose-mode' is non-nil, and disable it if `purpose-mode' is
nil. Functions should be added to this variable via `add-hook'.")

;; variable `purpose-mode' may not be defined yet, so declare it here (without a
;; value) to satisfy the byte-compiler.
(defvar purpose-mode)

(defun purpose-toggle-advice (symbol where function)
"Add advice or remove advice, depending on the value of `purpose-mode'.
If `purpose-mode' is active, then add FUNCTION to SYMBOL
according to WHERE, otherwise remove FUNCTION from SYMBOL. Refer
to `advice-add' and `advice-remove' for further details of
SYMBOL, WHERE and FUNCTION."
(if purpose-mode
(advice-add symbol where function)
(advice-remove symbol function)))

(defmacro purpose-advice-toggler (symbol where function)
"Return a function that adds or removes an advice, depending on
the value of `purpose-mode'."
;; no need for memoization. It's ok to return a lambda, because even if called
;; twice with same args, adding the two results to the same hook will not
;; create duplications in the hook: `add-hook' is smart enough to consider two
;; closures with equal code (and same captured values) as equal objects (it
;; checks equality with `member', which compares with `equal'). Verified with
;; Emacs 27.1
`(lambda ()
(purpose-toggle-advice ,symbol ,where ,function)))

(defun purpose-install-advice-toggler (symbol where function)
(purpose-toggle-advice symbol where function)
(add-hook 'purpose-fix-togglers-hook (purpose-advice-toggler symbol where function)))

(defun purpose--fix-edebug ()
"Integrates Edebug with Purpose."

Expand All @@ -55,7 +92,9 @@ spliting logic with `pop-to-buffer'."
(unless (memq (framep (selected-frame)) '(nil t pc))
(x-focus-frame (selected-frame)))
(set-window-hscroll window 0))
(advice-add 'edebug-pop-to-buffer :override 'purpose--edebug-pop-to-buffer-advice)))

(purpose-install-advice-toggler 'edebug-pop-to-buffer :override
'purpose--edebug-pop-to-buffer-advice)))

;;; `compilation-next-error-function' sometimes hides the compilation buffer
;;; when Purpose is on. Solution: make the buffer's window dedicated while
Expand Down Expand Up @@ -98,7 +137,8 @@ window-purpose."
(interactive (lambda (spec) (advice-eval-interactive-spec spec)))
(let ((display-buffer-overriding-action '(purpose--action-function . nil)))
(apply oldfun args)))
(advice-add 'next-error :around 'purpose--next-error))

(purpose-install-advice-toggler 'next-error :around 'purpose--next-error))


;;; Hydra's *LV* buffer should be ignored by Purpose
Expand Down Expand Up @@ -187,10 +227,11 @@ When `purpose--active-p' is nil, call original `neo-global--create-window'."
'(Neotree purpose-display-reuse-window-buffer
purpose-display-reuse-window-purpose
purpose--fix-display-neotree))
(advice-add 'neo-global--create-window
:around 'purpose-fix-neotree-create-window-advice)
(advice-add 'neo-open-file
:around 'purpose-fix-neotree-open-file-advice))

(purpose-install-advice-toggler 'neo-global--create-window :around
'purpose-fix-neotree-create-window-advice)
(purpose-install-advice-toggler 'neo-open-file :around
'purpose-fix-neotree-open-file-advice))

(defun purpose--fix-neotree ()
"Call `purpose--fix-neotree-1' after `neotree' is loaded."
Expand All @@ -213,10 +254,11 @@ Don't call this function before `org' is loaded."
(defun purpose--fix-org-get-location (oldfun &rest args)
"Make Purpose inactive during `org-get-location'."
(without-purpose (apply oldfun args)))
(advice-add 'org-switch-to-buffer-other-window
:around 'purpose--fix-org-switch-to-buffer-other-window)
(advice-add 'org-get-location
:around 'purpose--fix-org-get-location))

(purpose-install-advice-toggler 'org-switch-to-buffer-other-window :around
'purpose--fix-org-switch-to-buffer-other-window)
(purpose-install-advice-toggler 'org-get-location :around
'purpose--fix-org-get-location))

(defun purpose--fix-org-no-popups ()
"Call `purpose--fix-org-no-popups-1' after `org' is loaded."
Expand All @@ -233,8 +275,9 @@ Don't call this function before `popwin' is loaded."
(defun purpose--fix-popwin-replicate (oldfun &rest args)
"Make Purpose inactive during `popwin:replicate-window-config'."
(without-purpose (apply oldfun args)))
(advice-add 'popwin:replicate-window-config
:around 'purpose--fix-popwin-replicate))

(purpose-install-advice-toggler 'popwin:replicate-window-config
:around 'purpose--fix-popwin-replicate))

(defun purpose--fix-popwin ()
"Call `purpose--fix-popwin-1' after `popwin' is loaded."
Expand Down Expand Up @@ -280,10 +323,11 @@ Don't call this function before `popwin' is loaded."
(defun purpose--fix-magit-popup-help (oldfun &rest args)
"Make Purpose inactive during `magit-popup-manpage'."
(without-purpose (apply oldfun args)))
(advice-add 'magit-popup-describe-function
:around 'purpose--fix-magit-popup-help)
(advice-add 'magit-popup-manpage
:around 'purpose--fix-magit-popup-help)))

(purpose-install-advice-toggler 'magit-popup-describe-function
:around 'purpose--fix-magit-popup-help)
(purpose-install-advice-toggler 'magit-popup-manpage
:around 'purpose--fix-magit-popup-help)))



Expand All @@ -307,8 +351,9 @@ Don't call this function before `popwin' is loaded."
(special-mode)
(goto-char (point-min)))
(switch-to-buffer buffer))
(advice-add 'whitespace-display-window :override
'purpose--whitespace-display-window-advice)))

(purpose-install-advice-toggler 'whitespace-display-window :override
'purpose--whitespace-display-window-advice)))


;;; install fixes
Expand All @@ -334,8 +379,8 @@ are:
(unless (member 'edebug exclude)
(purpose--fix-edebug))
(unless (member 'compilation-next-error-function exclude)
(advice-add 'compilation-next-error-function
:around #'purpose--fix-compilation-next-error))
(purpose-install-advice-toggler 'compilation-next-error-function
:around #'purpose--fix-compilation-next-error))
(unless (member 'isearch exclude)
(purpose--fix-isearch))
(unless (member 'next-error exclude)
Expand Down
8 changes: 6 additions & 2 deletions window-purpose.el
Original file line number Diff line number Diff line change
Expand Up @@ -298,9 +298,13 @@ This function is called when `purpose-mode' is deactivated."
(setq display-buffer-overriding-action
'(purpose--action-function . nil))
(setq purpose--active-p t)
(purpose-fix-install))
(unless purpose-fix-togglers-hook
(purpose-fix-install))
(run-hooks 'purpose-fix-togglers-hook))

(purpose--remove-advices)
(setq purpose--active-p nil)))
(setq purpose--active-p nil)
(run-hooks 'purpose-fix-togglers-hook)))

(push '(purpose-dedicated . writable) window-persistent-parameters)
(provide 'window-purpose)
Expand Down

0 comments on commit 655df54

Please sign in to comment.