diff --git a/window-purpose-configuration.el b/window-purpose-configuration.el index 99be102..82bb964 100644 --- a/window-purpose-configuration.el +++ b/window-purpose-configuration.el @@ -59,10 +59,7 @@ ;;; Types -;; `purpose-conf' is not an autoload because there is a bug in autoloading -;; `defclass' in Emacs 24.3. (no problem with Emacs 24.4) -;; If we decide to drop support for Emacs 24.3, we can make `purpose-conf' an -;; autoload again. +;;;###autoload (defclass purpose-conf () ((mode-purposes :initarg :mode-purposes :initform '() @@ -376,8 +373,7 @@ configuration. Example: (purpose-set-extension-configuration :python - (purpose-conf \"py\" - :mode-purposes + (purpose-conf :mode-purposes '((python-mode . python) (inferior-python-mode . interpreter)))) diff --git a/window-purpose-core.el b/window-purpose-core.el index b27225b..bb30a59 100644 --- a/window-purpose-core.el +++ b/window-purpose-core.el @@ -27,6 +27,7 @@ ;;; Code: (require 'window-purpose-configuration) +(eval-when-compile (require 'subr-x)) (defgroup purpose nil "purpose-mode configuration" @@ -190,7 +191,7 @@ FRAME defaults to the selected frame." (delete-dups (append (list default-purpose) (purpose-flatten - (mapcar #'purpose-hash-table-values + (mapcar #'hash-table-values (append (when purpose-use-default-configuration (list purpose--default-name-purposes purpose--default-mode-purposes diff --git a/window-purpose-fixes.el b/window-purpose-fixes.el index 3df9ffe..9ab105a 100644 --- a/window-purpose-fixes.el +++ b/window-purpose-fixes.el @@ -35,30 +35,19 @@ ;;; when Purpose is on. Solution: make the buffer's window dedicated while ;;; executing `compilation-next-error-function' -(define-purpose-compatible-advice 'compilation-next-error-function - :around purpose--fix-compilation-next-error - (&rest args) - "Integrate Purpose and `compilation-next-error-function'. +(defun purpose--fix-compilation-next-error (oldfun &rest args) + "Integrate Purpose and `compilation-next-error-function'. Advice that prevents `compilation-next-error-function' from hiding the compilation buffer. This is done by ensuring that the buffer is dedicated for the duration of the function. This function should be advised around `compilation-next-error-function'." - ;; new style advice - ((let* ((compilation-window (get-buffer-window (marker-buffer (point-marker)))) - (old-window-dedicated-p (window-dedicated-p compilation-window))) - (set-window-dedicated-p compilation-window t) - (unwind-protect - (apply oldfun args) - (set-window-dedicated-p compilation-window old-window-dedicated-p)))) - - ;; old style advice - ((let* ((compilation-window (get-buffer-window (marker-buffer (point-marker)))) - (old-window-dedicated-p (window-dedicated-p compilation-window))) - (set-window-dedicated-p compilation-window t) - (unwind-protect - ad-do-it - (set-window-dedicated-p compilation-window old-window-dedicated-p))))) + (let* ((compilation-window (get-buffer-window (marker-buffer (point-marker)))) + (old-window-dedicated-p (window-dedicated-p compilation-window))) + (set-window-dedicated-p compilation-window t) + (unwind-protect + (apply oldfun args) + (set-window-dedicated-p compilation-window old-window-dedicated-p)))) @@ -72,8 +61,7 @@ This function should be advised around ;;; Helm's buffers should be ignored, and they should have their own purpose (defvar purpose--helm-conf - (purpose-conf "helm" - :regexp-purposes '(("^\\*Helm" . helm) + (purpose-conf :regexp-purposes '(("^\\*Helm" . helm) ("^\\*helm" . helm))) "Purpose configuration for helm.") (defun purpose--fix-helm () @@ -124,47 +112,33 @@ Override the display and creation of the neotree window. When opening files from the neotree window, use Purpose only when necessary. Note: Don't call this function before `neotree' is loaded." - (define-purpose-compatible-advice 'neo-global--create-window - :around purpose-fix-neotree-create-window-advice - (&rest args) - "Override `neo-global--create-window' with `purpose--fix-create-neo-window'. + (defun purpose-fix-neotree-create-window-advice (oldfun &rest args) + "Override `neo-global--create-window' with `purpose--fix-create-neo-window'. When `purpose--active-p' is nil, call original `neo-global--create-window'." - ;; new style adivce - ((if purpose--active-p - (purpose--fix-create-neo-window) - (apply oldfun args))) - ;; old style advice - ((if purpose--active-p - (setq ad-return-value (purpose--fix-create-neo-window)) - ad-do-it))) - - (define-purpose-compatible-advice 'neo-open-file - :around purpose-fix-neotree-open-file-advice - (full-path &optional arg) - "When ARG is nil, make sure Purpose is off while executing `neo-open-file'." - ;; new style advice - ((if (and purpose--active-p (null arg)) - (find-file full-path) - (without-purpose (funcall oldfun full-path arg)))) - ;; old style advice - ((if (and purpose--active-p (null arg)) - (setq ad-return-value (find-file full-path)) - (without-purpose ad-do-it)))) + (if purpose--active-p + (purpose--fix-create-neo-window) + (apply oldfun args))) + + (defun purpose-fix-neotree-open-file-advice (oldfun full-path &optional arg) + "When ARG is nil, make sure Purpose is off while executing `neo-open-file'." + (if (and purpose--active-p (null arg)) + (find-file full-path) + (without-purpose (funcall oldfun full-path arg)))) ;; using purpose 'Neotree, because using 'neotree causes problems with ;; `purpose-special-action-sequences' ('neotree is also a function, so ;; `purpose--special-action-sequence' will try to call it) (purpose-set-extension-configuration :neotree - (purpose-conf "Neotree" :name-purposes `((,neo-buffer-name . Neotree)))) + (purpose-conf :name-purposes `((,neo-buffer-name . Neotree)))) (add-to-list 'purpose-special-action-sequences '(Neotree purpose-display-reuse-window-buffer purpose-display-reuse-window-purpose purpose--fix-display-neotree)) - (purpose-advice-add 'neo-global--create-window - :around 'purpose-fix-neotree-create-window-advice) - (purpose-advice-add 'neo-open-file - :around 'purpose-fix-neotree-open-file-advice)) + (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)) (defun purpose--fix-neotree () "Call `purpose--fix-neotree-1' after `neotree' is loaded." @@ -181,26 +155,16 @@ When `purpose--active-p' is nil, call original `neo-global--create-window'." (defun purpose--fix-org-no-popups-1 () "Make Purpose inactive during some functions that use `org-no-popups'. Don't call this function before `org' is loaded." - (define-purpose-compatible-advice 'org-switch-to-buffer-other-window - :around purpose--fix-org-switch-to-buffer-other-window - (&rest args) - "Make Purpose inactive during `org-switch-to-buffer-other-window'." - ;; new style advice - ((without-purpose (apply oldfun args))) - ;; old style advice - ((without-purpose ad-do-it))) - (define-purpose-compatible-advice 'org-get-location - :around purpose--fix-org-get-location - (&rest args) - "Make Purpose inactive during `org-get-location'." - ;; new style advice - ((without-purpose (apply oldfun args))) - ;; old style advice - ((without-purpose ad-do-it))) - (purpose-advice-add 'org-switch-to-buffer-other-window - :around 'purpose--fix-org-switch-to-buffer-other-window) - (purpose-advice-add 'org-get-location - :around 'purpose--fix-org-get-location)) + (defun purpose--fix-org-switch-to-buffer-other-window (oldfun &rest args) + "Make Purpose inactive during `org-switch-to-buffer-other-window'." + (without-purpose (apply oldfun args))) + (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)) (defun purpose--fix-org-no-popups () "Call `purpose--fix-org-no-popups-1' after `org' is loaded." @@ -214,16 +178,11 @@ Don't call this function before `org' is loaded." (defun purpose--fix-popwin-1 () "Make Purpose inactive during `popwin:replicate-window-config'. Don't call this function before `popwin' is loaded." - (define-purpose-compatible-advice 'popwin:replicate-window-config - :around purpose--fix-popwin-replicate - (&rest args) - "Make Purpose inactive during `popwin:replicate-window-config'." - ;; new style advice - ((without-purpose (apply oldfun args))) - ;; old style advice - ((without-purpose ad-do-it))) - (purpose-advice-add 'popwin:replicate-window-config - :around 'purpose--fix-popwin-replicate)) + (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)) (defun purpose--fix-popwin () "Call `purpose--fix-popwin-1' after `popwin' is loaded." @@ -239,7 +198,6 @@ Don't call this function before `popwin' is loaded." '(purpose-set-extension-configuration :guide-key (purpose-conf - "guide-key" :name-purposes `((,guide-key/guide-buffer-name . guide-key)))))) @@ -254,7 +212,6 @@ Don't call this function before `popwin' is loaded." (purpose-set-extension-configuration :which-key (purpose-conf - "which-key" :name-purposes `((,which-key-buffer-name . which-key))))))) @@ -264,27 +221,16 @@ Don't call this function before `popwin' is loaded." "Let magit-popup display help windows the way it wants." (eval-after-load 'magit-popup '(progn - (define-purpose-compatible-advice 'magit-popup-describe-function - :around purpose--fix-magit-popup-help - (&rest args) - "Make Purpose inactive during `magit-popup-describe-function'." - ;; new style advice - ((without-purpose (apply oldfun args))) - ;; old style advice - ((without-purpose ad-do-it))) - (define-purpose-compatible-advice 'magit-popup-manpage - :around purpose--fix-magit-popup-help - (&rest args) - "Make Purpose inactive during `magit-popup-manpage'." - ;; new style advice - ((without-purpose (apply oldfun args))) - ;; old style advice - ((without-purpose ad-do-it))) - (purpose-advice-add 'magit-popup-describe-function - :around 'purpose--fix-magit-popup-help) - (purpose-advice-add 'magit-popup-manpage - :around 'purpose--fix-magit-popup-help) - ))) + (defun purpose--fix-magit-popup-help (oldfun &rest args) + "Make Purpose inactive during `magit-popup-describe-function'." + (without-purpose (apply oldfun args))) + (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)))) ;;; install fixes @@ -303,8 +249,8 @@ are: - 'which-key : don't integrate with which-key" (interactive) (unless (member 'compilation-next-error-function exclude) - (purpose-advice-add 'compilation-next-error-function - :around #'purpose--fix-compilation-next-error)) + (advice-add 'compilation-next-error-function + :around #'purpose--fix-compilation-next-error)) (unless (member 'lv exclude) (purpose--fix-hydra-lv)) (unless (member 'helm exclude) diff --git a/window-purpose-layout.el b/window-purpose-layout.el index 6553af0..3f3b387 100644 --- a/window-purpose-layout.el +++ b/window-purpose-layout.el @@ -29,6 +29,7 @@ (require 'cl-lib) (require 'ring) (require 'window-purpose-core) +(eval-when-compile (require 'subr-x)) (defconst purpose--built-in-layouts-dir (when load-file-name @@ -233,8 +234,8 @@ WINDOW must be a live window and defaults to the selected one." "Get a list of all filenames that end in SUFFIX in DIRECTORY. The base filenames without the suffix are returned." (cl-loop for filename in (directory-files directory nil nil t) - if (purpose--suffix-p suffix filename) - collect (purpose--remove-suffix suffix filename))) + if (string-suffix-p suffix filename) + collect (string-remove-suffix suffix filename))) (defun purpose--file-with-suffix (name suffix directory) "Get file with basename NAME and suffix SUFFIX in DIRECTORY. diff --git a/window-purpose-switch.el b/window-purpose-switch.el index f8a6afe..30166c6 100644 --- a/window-purpose-switch.el +++ b/window-purpose-switch.el @@ -775,7 +775,7 @@ If ALIST is nil, it is ignored and `purpose--alist' is used instead." (let* ((user-action-sequence .user-action-sequence) (special-action-sequence (purpose--special-action-sequence buffer alist)) - (normal-action-sequence (purpose-alist-get + (normal-action-sequence (alist-get (or .action-order purpose-default-action-order) purpose-action-sequences)) @@ -933,166 +933,93 @@ treat the funcion(s) as an action sequence." fn (list fn))))) -(define-purpose-compatible-advice 'display-buffer - :around purpose-display-buffer-advice - (buffer-or-name &optional action frame) - "Update `purpose--alist' when calling `display-buffer'." - ;; new style advice - ((let ((action-order (purpose-display--action-to-order action)) - (user-action-sequence (purpose-display--action-to-sequence action)) - (purpose--alist purpose--alist)) - (when action-order - (setq purpose--alist - (purpose-alist-set 'action-order action-order purpose--alist))) - (when user-action-sequence - (setq purpose--alist (purpose-alist-set 'user-action-sequence - user-action-sequence - purpose--alist))) - (funcall oldfun buffer-or-name action frame))) - - ;; old style advice - ((let* ((action-order (purpose-display--action-to-order action)) - (user-action-sequence (purpose-display--action-to-sequence action)) - (purpose--alist purpose--alist)) - (when action-order - (setq purpose--alist - (purpose-alist-set 'action-order action-order purpose--alist))) - (when user-action-sequence - (setq purpose--alist (purpose-alist-set 'user-action-sequence - user-action-sequence - purpose--alist))) - ad-do-it))) - -(define-purpose-compatible-advice 'switch-to-buffer - :around purpose-switch-to-buffer-advice - (buffer-or-name &optional norecord force-same-window) - "Advice for overriding `switch-to-buffer' conditionally. +(defun purpose-display-buffer-advice + (oldfun buffer-or-name &optional action frame) + "Update `purpose--alist' when calling `display-buffer'." + (let ((action-order (purpose-display--action-to-order action)) + (user-action-sequence (purpose-display--action-to-sequence action)) + (purpose--alist purpose--alist)) + (when action-order + (setq purpose--alist + (purpose-alist-set 'action-order action-order purpose--alist))) + (when user-action-sequence + (setq purpose--alist (purpose-alist-set 'user-action-sequence + user-action-sequence + purpose--alist))) + (funcall oldfun buffer-or-name action frame))) + +(defun purpose-switch-to-buffer-advice + (oldfun buffer-or-name &optional norecord force-same-window) + "Advice for overriding `switch-to-buffer' conditionally. If Purpose is active (`purpose--active-p' is non-nil), call `purpose-switch-buffer', otherwise call `switch-to-buffer'." - ;; new style advice - ((purpose-message "switch-to-buffer advice") - ;; check the full `purpose--use-action-function-p' here, because - ;; if purpose shouldn't be used for some reason (such as - ;; `purpose-action-function-ignore-buffer-names'), then we want - ;; to fallback to `switch-to-buffer', instead of - ;; `display-buffer' - (if (purpose--use-action-function-p (window-normalize-buffer-to-switch-to - buffer-or-name) - nil) - (purpose-switch-buffer buffer-or-name - norecord - ;; when `switch-to-buffer' is called - ;; interactively force-same-window is non-nil, - ;; but want it to be nil, so we check - ;; `called-interactively-p' as well - (and force-same-window - (not (called-interactively-p 'interactive)) - ;; `ivy--switch-buffer-action' replicates the - ;; interactive behavior, so handle the same as - ;; an interactive call - (not (member 'ivy--switch-buffer-action - (purpose--function-stack))))) - (funcall oldfun buffer-or-name norecord force-same-window))) - - ;; old style advice - ((purpose-message "switch-to-buffer advice") - (if (purpose--use-action-function-p - (window-normalize-buffer-to-switch-to buffer-or-name) nil) - (setq ad-return-value - (purpose-switch-buffer buffer-or-name - norecord - ;; when `switch-to-buffer' is called - ;; interactively force-same-window is non-nil, - ;; but want it to be nil, so we check - ;; `called-interactively-p' as well - (and force-same-window - (not (called-interactively-p 'interactive)) - ;; `ivy--switch-buffer-action' replicates the - ;; interactive behavior, so handle the same as - ;; an interactive call - (not (member 'ivy--switch-buffer-action - (purpose--function-stack)))))) - ad-do-it))) - -(define-purpose-compatible-advice 'switch-to-buffer-other-window - :around purpose-switch-to-buffer-other-window-advice - (buffer-or-name &optional norecord) - "Advice for overriding `switch-to-buffer-other-window' conditionally. + (purpose-message "switch-to-buffer advice") + ;; check the full `purpose--use-action-function-p' here, because + ;; if purpose shouldn't be used for some reason (such as + ;; `purpose-action-function-ignore-buffer-names'), then we want + ;; to fallback to `switch-to-buffer', instead of + ;; `display-buffer' + (if (purpose--use-action-function-p (window-normalize-buffer-to-switch-to + buffer-or-name) + nil) + (purpose-switch-buffer buffer-or-name + norecord + ;; when `switch-to-buffer' is called + ;; interactively force-same-window is non-nil, + ;; but want it to be nil, so we check + ;; `called-interactively-p' as well + (and force-same-window + (not (called-interactively-p 'interactive)) + ;; `ivy--switch-buffer-action' replicates the + ;; interactive behavior, so handle the same as + ;; an interactive call + (not (member 'ivy--switch-buffer-action + (purpose--function-stack))))) + (funcall oldfun buffer-or-name norecord force-same-window))) + +(defun purpose-switch-to-buffer-other-window-advice + (oldfun buffer-or-name &optional norecord) + "Advice for overriding `switch-to-buffer-other-window' conditionally. If Purpose is active (`purpose--active-p' is non-nil), call `purpose-switch-buffer-other-window', otherwise call `switch-to-buffer-other-window'." - ;; new style advice - ((purpose-message "switch-to-buffer-other-window advice") - (if purpose--active-p - (purpose-switch-buffer-other-window buffer-or-name norecord) - (funcall oldfun buffer-or-name norecord))) - - ;; old style advice - ((purpose-message "switch-to-buffer-other-window advice") - (if purpose--active-p - (setq ad-return-value - (purpose-switch-buffer-other-window buffer-or-name norecord)) - ad-do-it))) - -(define-purpose-compatible-advice 'switch-to-buffer-other-frame - :around purpose-switch-to-buffer-other-frame-advice - (buffer-or-name &optional norecord) - "Advice for overriding `switch-to-buffer-other-frame' conditionally. + (purpose-message "switch-to-buffer-other-window advice") + (if purpose--active-p + (purpose-switch-buffer-other-window buffer-or-name norecord) + (funcall oldfun buffer-or-name norecord))) + +(defun purpose-switch-to-buffer-other-frame-advice + (oldfun buffer-or-name &optional norecord) + "Advice for overriding `switch-to-buffer-other-frame' conditionally. If Purpose is active (`purpose--active-p' is non-nil), call `purpose-switch-buffer-other-frame', otherwise call `switch-to-buffer-other-frame'." - ;; new style advice - ((purpose-message "switch-to-buffer-other-frame advice") - (if purpose--active-p - (purpose-switch-buffer-other-frame buffer-or-name norecord) - (funcall oldfun buffer-or-name norecord))) - - ;; old style advice - ((purpose-message "switch-to-buffer-other-frame advice") - (if purpose--active-p - (setq ad-return-value - (purpose-switch-buffer-other-frame buffer-or-name norecord)) - ad-do-it))) - -(define-purpose-compatible-advice 'pop-to-buffer - :around purpose-pop-to-buffer-advice - (buffer-or-name &optional action norecord) - "Advice for overriding `pop-to-buffer' conditionally. + (purpose-message "switch-to-buffer-other-frame advice") + (if purpose--active-p + (purpose-switch-buffer-other-frame buffer-or-name norecord) + (funcall oldfun buffer-or-name norecord))) + +(defun purpose-pop-to-buffer-advice + (oldfun buffer-or-name &optional action norecord) + "Advice for overriding `pop-to-buffer' conditionally. If Purpose is active (`purpose--active-p' is non-nil) and ACTION is nil, call `purpose-pop-buffer', otherwise call `pop-to-buffer'." - ;; new style advice - ((purpose-message "pop-to-buffer advice") - (if (and purpose--active-p - (not action)) - (purpose-pop-buffer buffer-or-name norecord) - (funcall oldfun buffer-or-name action norecord))) - - ;; old style advice - ((purpose-message "pop-to-buffer advice") - (if (and purpose--active-p - (not action)) - (setq ad-return-value (purpose-pop-buffer buffer-or-name norecord)) - ad-do-it))) - -(define-purpose-compatible-advice 'pop-to-buffer-same-window - :around purpose-pop-to-buffer-same-window-advice - (buffer-or-name &optional norecord) - "Advice for overriding `pop-to-buffer-same-window' conditionally. + (purpose-message "pop-to-buffer advice") + (if (and purpose--active-p + (not action)) + (purpose-pop-buffer buffer-or-name norecord) + (funcall oldfun buffer-or-name action norecord))) + +(defun purpose-pop-to-buffer-same-window-advice + (oldfun buffer-or-name &optional norecord) + "Advice for overriding `pop-to-buffer-same-window' conditionally. If Purpose is active (`purpose--active-p' is non-nil), call `purpose-pop-buffer-same-window', otherwise call `pop-to-buffer-same-window'." - ;; new style advice - ((purpose-message "pop-to-buffer-same-window advice") - (if purpose--active-p - (purpose-pop-buffer-same-window buffer-or-name norecord) - (funcall oldfun buffer-or-name norecord))) - - ;; old style advice - ((purpose-message "pop-to-buffer-same-window advice") - (if purpose--active-p - (setq ad-return-value - (purpose-pop-buffer-same-window buffer-or-name norecord)) - ad-do-it))) + (purpose-message "pop-to-buffer-same-window advice") + (if purpose--active-p + (purpose-pop-buffer-same-window buffer-or-name norecord) + (funcall oldfun buffer-or-name norecord))) ;; anti-override: diff --git a/window-purpose-utils.el b/window-purpose-utils.el index 3ae5fb7..55d19df 100644 --- a/window-purpose-utils.el +++ b/window-purpose-utils.el @@ -26,8 +26,6 @@ ;;; Code: (require 'cl-lib) -;; subr-x isn't available in 24.3 -(require 'subr-x nil t) (defcustom purpose-message-on-p nil "If non-nil, `purpose-message' will produce a message. @@ -45,17 +43,6 @@ return the formatted string. FORMAT-STRING and ARGS are passed to (apply #'message format-string args) (apply #'format format-string args))) -;; define our (limited) version of alist-get -(defun purpose-alist-get (key alist &optional default _remove) - "Get KEY's value in ALIST. -If no such key, return DEFAULT. -When setting KEY's value, if the new value is equal to DEFAULT and -REMOVE is non-nil, then delete the KEY instead." - (let ((entry (assq key alist))) - (if entry - (cdr entry) - default))) - (defun purpose-alist-set (key value alist) "Set VALUE to be the value associated to KEY in ALIST. This doesn't change the original alist, but returns a modified copy." @@ -102,68 +89,6 @@ Example: -;;; compatibility layer for advices - -(defun purpose-advice-convert-where-arg (where) - "Convert WHERE argument from new advice style to old advice style. -New style is :before, :after, etc. Old style is 'before, 'after, etc." - (unless (keywordp where) - (signal 'wrong-type-argument `(keywordp ,where))) - (if (eq where :override) - 'around - (intern (mapconcat #'identity (cdr (split-string (symbol-name where) ":")) ":")))) - -(defun purpose-advice-new-style-arglist (arglist where) - "Convert ARGLIST to new style, according to WHERE. -If WHERE is :around, add 'oldfun to the beginning of ARGLIST. -Otherwise, return ARGLIST without changes." - (if (eql where :around) - (append '(oldfun) arglist) - arglist)) - -(defmacro define-purpose-compatible-advice (symbol where name arglist docstring new-body old-body) - "Define advice, using new or old advice style as appropriate. -SYMBOL and WHERE have the same meaning as in `advice-add'. NAME -has the same meaning as FUNCTION argument of `advice-add'. -ARGLIST has the same meaning as in `defadvice'. DOCSTRING is the -advice's documentation. NEW-BODY is the advice's body if the new -advice style is available. OLD-BODY is the advice's body if the -new advice style is unavailable. - -`define-purpose-compatible-advice' properly supports only :around, :before and :after advices." - (declare (indent 5) (debug (&define sexp sexp name lambda-list stringp (&rest form) (&rest form)))) - (if (fboundp 'advice-add) - `(defun ,name (,@(purpose-advice-new-style-arglist arglist where)) - ,docstring - ,@new-body) - ;; ,(cadr symbol) turns <'foo> into - `(defadvice ,(cadr symbol) (,(purpose-advice-convert-where-arg where) ,name ,arglist) - ,docstring - ,@old-body))) - -(defmacro purpose-advice-add (symbol where name) - "Enable advice, using new or old advice style as appropriate. -SYMBOL, WHERE and NAME have the same meaning as in -`define-purpose-advice'." - (declare (indent nil) (debug 0)) - (if (fboundp 'advice-add) - `(advice-add ,symbol ,where ,name) - `(progn - (ad-enable-advice ,symbol ',(purpose-advice-convert-where-arg where) ,name) - (ad-update ,symbol) - (ad-activate ,symbol)))) - -(defmacro purpose-advice-remove (symbol where name) - "Disable advice, using new or old advice style as appropriate. -SYMBOL, WHERE and NAME have the same meaning as in -`define-purpose-advice'." - (declare (indent nil) (debug 0)) - (if (fboundp 'advice-remove) - `(advice-remove ,symbol ,name) - `(progn - (ad-disable-advice ,symbol ',(purpose-advice-convert-where-arg where) ,name) - (ad-update ,symbol)))) - (defun purpose--iter-hash (function table) "Like `maphash', but return a list the results of calling FUNCTION for each entry in hash-table TABLE." @@ -175,13 +100,6 @@ for each entry in hash-table TABLE." table) results)) -(defalias 'purpose-hash-table-values - (if (fboundp 'hash-table-values) - #'hash-table-values - (lambda (hash-table) - "Return all values in HASH-TABLE." - (purpose--iter-hash (lambda (_kk vv) vv) hash-table)))) - ;; taken from http://emacs.stackexchange.com/a/7405/6533, credit to Jordon Biondo (defun purpose--call-stack () "Return the current call stack frames." @@ -198,28 +116,5 @@ for each entry in hash-table TABLE." "Like `purpose--call-stack' but is a list of only the function names." (butlast (mapcar 'cl-second (purpose--call-stack)))) -(defalias 'purpose--suffix-p - (if (fboundp 'string-suffix-p) - #'string-suffix-p - ;; taken from string-suffix-p in subr.el in Emacs 24.5.1 - (lambda (suffix string &optional ignore-case) - "Return non-nil if SUFFIX is a suffix of STRING. -If IGNORE-CASE is non-nil, the comparison is done without paying -attention to case differences." - (let ((start-pos (- (length string) (length suffix)))) - (and (>= start-pos 0) - (eq t (compare-strings suffix nil nil - string start-pos nil ignore-case))))))) - -(defalias 'purpose--remove-suffix - (if (fboundp 'string-remove-suffix) - #'string-remove-suffix - ;; based on string-remove-suffix in subr-x.el in Emacs 24.5.1 - (lambda (suffix string) - "Remove SUFFIX from STRING if present." - (if (purpose--suffix-p suffix string) - (substring string 0 (- (length string) (length suffix))) - string)))) - (provide 'window-purpose-utils) ;;; window-purpose-utils.el ends here diff --git a/window-purpose-x.el b/window-purpose-x.el index b558ee7..4a1b6f1 100644 --- a/window-purpose-x.el +++ b/window-purpose-x.el @@ -70,8 +70,7 @@ All windows are purpose-dedicated.") ;; the name arg ("purpose-x-code1") is necessary for Emacs 24.3 and older (defvar purpose-x-code1-purpose-config - (purpose-conf "purpose-x-code1" - :mode-purposes + (purpose-conf :mode-purposes '((ibuffer-mode . buffers) (dired-mode . dired) (imenu-list-major-mode . ilist)))) @@ -190,13 +189,11 @@ imenu." ;;; - `purpose-x-magit-off' (defvar purpose-x-magit-single-conf - (purpose-conf "magit-single" - :regexp-purposes '(("^\\*magit" . magit))) + (purpose-conf :regexp-purposes '(("^\\*magit" . magit))) "Configuration that gives each magit major mode the same purpose.") (defvar purpose-x-magit-multi-conf (purpose-conf - "magit-multi" :mode-purposes '((magit-diff-mode . magit-diff) (magit-status-mode . magit-status) (magit-log-mode . magit-log) @@ -384,7 +381,6 @@ The configuration is updated according to (interactive) (cl-flet ((joiner (x) (cons x 'popup))) (let ((conf (purpose-conf - "popwin" :mode-purposes (mapcar #'joiner purpose-x-popwin-major-modes) :name-purposes (mapcar #'joiner purpose-x-popwin-buffer-names) :regexp-purposes (mapcar #'joiner @@ -673,12 +669,9 @@ window-local buffer lists." ;; Unrecord BUFFER in WINDOW. (unrecord-window-buffer window buffer))))) -(define-purpose-compatible-advice 'replace-buffer-in-windows - :override purpose-x-replace-buffer-in-windows - (&optional buffer-or-name) - "Override `replace-buffer-in-windows' with a purpose-aware version." - ((purpose-x-replace-buffer-in-windows-1 buffer-or-name)) - ((setq ad-return-value (purpose-x-replace-buffer-in-windows-1 buffer-or-name)))) +(defun purpose-x-replace-buffer-in-windows (&optional buffer-or-name) + "Override `replace-buffer-in-windows' with a purpose-aware version." + (purpose-x-replace-buffer-in-windows-1 buffer-or-name)) (defun purpose-x-kill-sync () "Synchronize `replace-buffer-in-windows' with `purpose-mode'. @@ -686,8 +679,8 @@ If `purpose-mode' is enabled, override `replace-buffer-in-windows' with `purpose-x-replace-buffer-in-windows'. If `purpose-mode' is disabled, cancel the override of `replace-buffer-in-windows'." (if purpose-mode - (purpose-advice-add 'replace-buffer-in-windows :override 'purpose-x-replace-buffer-in-windows) - (purpose-advice-remove 'replace-buffer-in-windows :override 'purpose-x-replace-buffer-in-windows))) + (advice-add 'replace-buffer-in-windows :override 'purpose-x-replace-buffer-in-windows) + (advice-remove 'replace-buffer-in-windows 'purpose-x-replace-buffer-in-windows))) ;;;###autoload (defun purpose-x-kill-setup () @@ -708,7 +701,7 @@ This is implemented by overriding `replace-buffer-in-windows' with (defun purpose-x-kill-unset () "Deactivate purpose-x-kill extension." (interactive) - (purpose-advice-remove 'replace-buffer-in-windows :override 'purpose-x-replace-buffer-in-windows) + (advice-remove 'replace-buffer-in-windows 'purpose-x-replace-buffer-in-windows) (remove-hook 'purpose-mode-hook 'purpose-x-kill-sync)) ;;; --- purpose-x-kill ends here --- diff --git a/window-purpose.el b/window-purpose.el index b00ed69..4ccad3b 100644 --- a/window-purpose.el +++ b/window-purpose.el @@ -7,7 +7,7 @@ ;; Version: 1.6.1 ;; Keywords: frames ;; Homepage: https://github.com/bmag/emacs-purpose -;; Package-Requires: ((emacs "24") (cl-lib "0.5") (let-alist "1.0.3") (imenu-list "0.1")) +;; Package-Requires: ((emacs "25") (imenu-list "0.1")) ;; This file is not part of GNU Emacs. @@ -272,34 +272,22 @@ Some examples: (defun purpose--add-advices () "Add all advices needed for Purpose to work. This function is called when `purpose-mode' is activated." - (purpose-advice-add 'switch-to-buffer :around - #'purpose-switch-to-buffer-advice) - (purpose-advice-add 'switch-to-buffer-other-window :around - #'purpose-switch-to-buffer-other-window-advice) - (purpose-advice-add 'switch-to-buffer-other-frame :around - #'purpose-switch-to-buffer-other-frame-advice) - (purpose-advice-add 'pop-to-buffer :around - #'purpose-pop-to-buffer-advice) - (purpose-advice-add 'pop-to-buffer-same-window :around - #'purpose-pop-to-buffer-same-window-advice) - (purpose-advice-add 'display-buffer :around - #'purpose-display-buffer-advice)) + (advice-add 'switch-to-buffer :around #'purpose-switch-to-buffer-advice) + (advice-add 'switch-to-buffer-other-window :around #'purpose-switch-to-buffer-other-window-advice) + (advice-add 'switch-to-buffer-other-frame :around #'purpose-switch-to-buffer-other-frame-advice) + (advice-add 'pop-to-buffer :around #'purpose-pop-to-buffer-advice) + (advice-add 'pop-to-buffer-same-window :around #'purpose-pop-to-buffer-same-window-advice) + (advice-add 'display-buffer :around #'purpose-display-buffer-advice)) (defun purpose--remove-advices () "Remove all advices needed for Purpose to work. This function is called when `purpose-mode' is deactivated." - (purpose-advice-remove 'switch-to-buffer :around - #'purpose-switch-to-buffer-advice) - (purpose-advice-remove 'switch-to-buffer-other-window :around - #'purpose-switch-to-buffer-other-window-advice) - (purpose-advice-remove 'switch-to-buffer-other-frame :around - #'purpose-switch-to-buffer-other-frame-advice) - (purpose-advice-remove 'pop-to-buffer :around - #'purpose-pop-to-buffer-advice) - (purpose-advice-remove 'pop-to-buffer-same-window :around - #'purpose-pop-to-buffer-same-window-advice) - (purpose-advice-remove 'display-buffer :around - #'purpose-display-buffer-advice)) + (advice-remove 'switch-to-buffer #'purpose-switch-to-buffer-advice) + (advice-remove 'switch-to-buffer-other-window #'purpose-switch-to-buffer-other-window-advice) + (advice-remove 'switch-to-buffer-other-frame #'purpose-switch-to-buffer-other-frame-advice) + (advice-remove 'pop-to-buffer #'purpose-pop-to-buffer-advice) + (advice-remove 'pop-to-buffer-same-window #'purpose-pop-to-buffer-same-window-advice) + (advice-remove 'display-buffer #'purpose-display-buffer-advice)) ;;;###autoload (define-minor-mode purpose-mode nil