From b5416d971a720e1dfb9aedd8e7d23f24b1ea5325 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Tue, 25 May 2021 11:47:51 +0200 Subject: Improve windmove-*-default-keybindings functions (bug#41438) * windmove.el (windmove-mode-map): Add special map for windmove commands. (windmove-mode): Add minor mode for activating windmove-mode-map. (windmove-install-defaults): Add general function for manipulating windmove-mode-map. (windmove-default-keybindings): Use windmove-install-defaults. (windmove-display-default-keybindings): Use windmove-install-defaults. (windmove-delete-default-keybindings): Use windmove-install-defaults. (windmove-swap-states-default-keybindings): Use windmove-install-defaults. --- lisp/windmove.el | 91 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 70 insertions(+), 21 deletions(-) (limited to 'lisp/windmove.el') diff --git a/lisp/windmove.el b/lisp/windmove.el index e4ea8e0f693..ea4486348be 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -426,19 +426,53 @@ unless `windmove-create-window' is non-nil and a new window is created." ;; I don't think these bindings will work on non-X terminals; you ;; probably want to use different bindings in that case. +(defvar windmove-mode-map (make-sparse-keymap) + "Map used by `windmove-install-defaults'.") + +(define-minor-mode windmove-mode + "Global minor mode for default windmove commands." + :keymap windmove-mode-map + :init-value t + :global t) + +(defun windmove-install-defaults (prefix modifiers alist &optional uninstall) + "Install keys as specified by ALIST. +Every element of ALIST has the form (FN KEY), where KEY is +appended to MODIFIERS, adding PREFIX to the beginning, before +installing the key. Previous bindings of FN are unbound. +If UNINSTALL is non-nil, just remove the keys from ALIST." + (dolist (bind alist) + (dolist (old (where-is-internal (car bind) windmove-mode-map)) + (define-key windmove-mode-map old nil)) + (unless uninstall + (let ((key (vconcat (if (or (equal prefix [ignore]) + (eq prefix 'none)) + nil prefix) + (list (append modifiers (cdr bind)))))) + (when (eq (key-binding key) #'self-insert-command) + (warn "Command %S is shadowing self-insert-key" (car bind))) + (let ((old-fn (lookup-key windmove-mode-map key))) + (when (functionp old-fn) + (warn "Overriding %S with %S" old-fn (car bind)))) + (define-key windmove-mode-map key (car bind)))))) + ;;;###autoload (defun windmove-default-keybindings (&optional modifiers) "Set up keybindings for `windmove'. Keybindings are of the form MODIFIERS-{left,right,up,down}, where MODIFIERS is either a list of modifiers or a single modifier. +If MODIFIERS is `none', the keybindings will be directly bound to +the arrow keys. Default value of MODIFIERS is `shift'." (interactive) (unless modifiers (setq modifiers 'shift)) + (when (eq modifiers 'none) (setq modifiers nil)) (unless (listp modifiers) (setq modifiers (list modifiers))) - (global-set-key (vector (append modifiers '(left))) 'windmove-left) - (global-set-key (vector (append modifiers '(right))) 'windmove-right) - (global-set-key (vector (append modifiers '(up))) 'windmove-up) - (global-set-key (vector (append modifiers '(down))) 'windmove-down)) + (windmove-install-defaults nil modifiers + '((windmove-left left) + (windmove-right right) + (windmove-up up) + (windmove-down down)))) ;;; Directional window display and selection @@ -546,17 +580,21 @@ See the logic of the prefix ARG in `windmove-display-in-direction'." Keys are bound to commands that display the next buffer in the specified direction. Keybindings are of the form MODIFIERS-{left,right,up,down}, where MODIFIERS is either a list of modifiers or a single modifier. +If MODIFIERS is `none', the keybindings will be directly bound to +the arrow keys. Default value of MODIFIERS is `shift-meta'." (interactive) (unless modifiers (setq modifiers '(shift meta))) + (when (eq modifiers 'none) (setq modifiers nil)) (unless (listp modifiers) (setq modifiers (list modifiers))) - (global-set-key (vector (append modifiers '(left))) 'windmove-display-left) - (global-set-key (vector (append modifiers '(right))) 'windmove-display-right) - (global-set-key (vector (append modifiers '(up))) 'windmove-display-up) - (global-set-key (vector (append modifiers '(down))) 'windmove-display-down) - (global-set-key (vector (append modifiers '(?0))) 'windmove-display-same-window) - (global-set-key (vector (append modifiers '(?f))) 'windmove-display-new-frame) - (global-set-key (vector (append modifiers '(?t))) 'windmove-display-new-tab)) + (windmove-install-defaults nil modifiers + '((windmove-display-left left) + (windmove-display-right right) + (windmove-display-up up) + (windmove-display-down down) + (windmove-display-same-window ?0) + (windmove-display-new-frame ?f) + (windmove-display-new-tab ?t)))) ;;; Directional window deletion @@ -618,16 +656,22 @@ select the window that was below the current one." Keys are bound to commands that delete windows in the specified direction. Keybindings are of the form PREFIX MODIFIERS-{left,right,up,down}, where PREFIX is a prefix key and MODIFIERS is either a list of modifiers or -a single modifier. Default value of PREFIX is `C-x' and MODIFIERS is `shift'." +a single modifier. +If PREFIX is `none', no prefix is used. If MODIFIERS is `none', the keybindings +are directly bound to the arrow keys. +Default value of PREFIX is `C-x' and MODIFIERS is `shift'." (interactive) (unless prefix (setq prefix '(?\C-x))) + (when (eq prefix 'none) (setq prefix nil)) (unless (listp prefix) (setq prefix (list prefix))) (unless modifiers (setq modifiers '(shift))) + (when (eq modifiers 'none) (setq modifiers nil)) (unless (listp modifiers) (setq modifiers (list modifiers))) - (global-set-key (vector prefix (append modifiers '(left))) 'windmove-delete-left) - (global-set-key (vector prefix (append modifiers '(right))) 'windmove-delete-right) - (global-set-key (vector prefix (append modifiers '(up))) 'windmove-delete-up) - (global-set-key (vector prefix (append modifiers '(down))) 'windmove-delete-down)) + (windmove-install-defaults prefix modifiers + '((windmove-delete-left left) + (windmove-delete-right right) + (windmove-delete-up up) + (windmove-delete-down down)))) ;;; Directional window swap states @@ -673,14 +717,19 @@ from the opposite side of the frame." Keys are bound to commands that swap the states of the selected window with the window in the specified direction. Keybindings are of the form MODIFIERS-{left,right,up,down}, where MODIFIERS is either a list of modifiers -or a single modifier. Default value of MODIFIERS is `shift-super'." +or a single modifier. +If MODIFIERS is `none', the keybindings will be directly bound to the +arrow keys. +Default value of MODIFIERS is `shift-super'." (interactive) (unless modifiers (setq modifiers '(shift super))) + (when (eq modifiers 'none) (setq modifiers nil)) (unless (listp modifiers) (setq modifiers (list modifiers))) - (global-set-key (vector (append modifiers '(left))) 'windmove-swap-states-left) - (global-set-key (vector (append modifiers '(right))) 'windmove-swap-states-right) - (global-set-key (vector (append modifiers '(up))) 'windmove-swap-states-up) - (global-set-key (vector (append modifiers '(down))) 'windmove-swap-states-down)) + (windmove-install-defaults nil modifiers + '((windmove-swap-states-left left) + (windmove-swap-states-right right) + (windmove-swap-states-up up) + (windmove-swap-states-down down)))) (provide 'windmove) -- cgit v1.2.3 From 3916bf00c56274b39f921217168669f445e0df14 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Thu, 27 May 2021 12:24:42 +0200 Subject: Add user options for default windmove commands (bug#41438) * windmove.el (windmove--default-keybindings-type): Add type. (windmove-default-keybindings): Add user option. (windmove-display-default-keybindings): Add user option. (windmove-delete-default-keybindings): Add user option. (windmove-swap-states-default-keybindings): Add user option. --- lisp/windmove.el | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) (limited to 'lisp/windmove.el') diff --git a/lisp/windmove.el b/lisp/windmove.el index ea4486348be..0eba97a91b7 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -731,6 +731,86 @@ Default value of MODIFIERS is `shift-super'." (windmove-swap-states-up up) (windmove-swap-states-down down)))) + + +(defconst windmove--default-keybindings-type + `(choice (const :tag "Don't bind" nil) + (cons :tag "Bind using" + (key-sequence :tag "Prefix") + (set :tag "Modifier" + :greedy t + ;; See `(elisp) Keyboard Events' + (const :tag "Meta" meta) + (const :tag "Control" control) + (const :tag "Shift" shift) + (const :tag "Hyper" hyper) + (const :tag "Super" super) + (const :tag "Alt" alt)))) + "Customisation type for windmove modifiers.") + +(defcustom windmove-default-keybindings nil + "Default bindings for regular windmove commands." + :set (lambda (sym val) + (windmove-install-defaults + (car val) (cdr val) + '((windmove-left left) + (windmove-right right) + (windmove-up up) + (windmove-down down)) + (null val)) + (set-default sym val)) + :type windmove--default-keybindings-type + :version "28.1" + :group 'windmove) + +(defcustom windmove-display-default-keybindings nil + "Default bindings for display windmove commands." + :set (lambda (sym val) + (windmove-install-defaults + (car val) (cdr val) + '((windmove-display-left left) + (windmove-display-right right) + (windmove-display-up up) + (windmove-display-down down) + (windmove-display-same-window ?0) + (windmove-display-new-frame ?f) + (windmove-display-new-tab ?t)) + (null val)) + (set-default sym val)) + :type windmove--default-keybindings-type + :version "28.1" + :group 'windmove) + +(defcustom windmove-delete-default-keybindings nil + "Default bindings for delete windmove commands." + :set (lambda (sym val) + (windmove-install-defaults + (car val) (cdr val) + '((windmove-delete-left left) + (windmove-delete-right right) + (windmove-delete-up up) + (windmove-delete-down down)) + (null val)) + (set-default sym val)) + :type windmove--default-keybindings-type + :version "28.1" + :group 'windmove) + +(defcustom windmove-swap-states-default-keybindings nil + "Default bindings for swap-state windmove commands." + :set (lambda (sym val) + (windmove-install-defaults + (car val) (cdr val) + '((windmove-swap-states-left left) + (windmove-swap-states-right right) + (windmove-swap-states-up up) + (windmove-swap-states-down down)) + (null val)) + (set-default sym val)) + :type windmove--default-keybindings-type + :version "28.1" + :group 'windmove) + (provide 'windmove) -- cgit v1.2.3 From b516887283ce77cf3c0977154f713ef485e3e8a9 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Fri, 4 Jun 2021 09:48:13 +0300 Subject: Fix documentation of recent 'windmove' changes * lisp/windmove.el (windmove-default-keybindings) (windmove-display-default-keybindings) (windmove-delete-default-keybindings) (windmove-swap-states-default-keybindings): Improve doc strings. (Bug#41438) * etc/NEWS: Fix a typo in the 'windmove' entry. --- etc/NEWS | 4 ++-- lisp/windmove.el | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) (limited to 'lisp/windmove.el') diff --git a/etc/NEWS b/etc/NEWS index 8b207001fe5..675925906cb 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -557,8 +557,8 @@ disabled entirely. ** Windmove -*** New user options can be used to customize windmove keybindings. -There options include 'windmove-default-keybindings', +*** New user options to customize windmove keybindings. +These options include 'windmove-default-keybindings', 'windmove-display-default-keybindings', 'windmove-delete-default-keybindings', 'windmove-swap-states-default-keybindings'. diff --git a/lisp/windmove.el b/lisp/windmove.el index 0eba97a91b7..f5589036812 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -749,7 +749,8 @@ Default value of MODIFIERS is `shift-super'." "Customisation type for windmove modifiers.") (defcustom windmove-default-keybindings nil - "Default bindings for regular windmove commands." + "Default keybindings for regular windmove commands. +See `windmove-default-keybindings' for more detail." :set (lambda (sym val) (windmove-install-defaults (car val) (cdr val) @@ -764,7 +765,8 @@ Default value of MODIFIERS is `shift-super'." :group 'windmove) (defcustom windmove-display-default-keybindings nil - "Default bindings for display windmove commands." + "Default keybindings for windmove directional buffer display commands. +See `windmove-display-default-keybindings' for more detail." :set (lambda (sym val) (windmove-install-defaults (car val) (cdr val) @@ -782,7 +784,8 @@ Default value of MODIFIERS is `shift-super'." :group 'windmove) (defcustom windmove-delete-default-keybindings nil - "Default bindings for delete windmove commands." + "Default keybindings for windmove directional window deletion commands. +See `windmove-delete-default-keybindings' for more detail." :set (lambda (sym val) (windmove-install-defaults (car val) (cdr val) @@ -797,7 +800,8 @@ Default value of MODIFIERS is `shift-super'." :group 'windmove) (defcustom windmove-swap-states-default-keybindings nil - "Default bindings for swap-state windmove commands." + "Default keybindings for windmove's directional window swap-state commands. +See `windmove-swap-states-default-keybindings' for more detail." :set (lambda (sym val) (windmove-install-defaults (car val) (cdr val) -- cgit v1.2.3 From 0367d17482804cd4a47d6fcf0201cdded7fc88dc Mon Sep 17 00:00:00 2001 From: pillule Date: Wed, 16 Jun 2021 02:23:13 +0300 Subject: User option to select 'no-other-window' with windmove (bug#48916) * lisp/windmove.el (windmove-wrap-around): Remove superfluous :group tag. (windmove-create-window): Remove superfluous :group tag. (windmove-window-distance-delta): Remove superfluous :group tag. (windmove-allow-all-windows): Add new user option to allow the commands of windmove to target windows with the 'no-other-window parameter. (windmove-find-other-window): Use windmove-allow-all-windows. (windmove-display-no-select): Remove superfluous :group tag. (windmove-display-in-direction): Use windmove-allow-all-windows. (windmove-delete-in-direction): Use windmove-allow-all-windows. (windmove-swap-states-in-direction): Use windmove-allow-all-windows. (windmove-default-keybindings): Remove superfluous :group tag. (windmove-display-default-keybindings): Remove superfluous :group tag. (windmove-delete-default-keybindings): Remove superfluous :group tag. (windmove-swap-states-default-keybindings): Remove superfluous :group tag. --- lisp/windmove.el | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) (limited to 'lisp/windmove.el') diff --git a/lisp/windmove.el b/lisp/windmove.el index f5589036812..ac146ab2dc7 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -138,8 +138,7 @@ If this variable is set to t, moving left from the leftmost window in a frame will find the rightmost one, and similarly for the other directions. The minibuffer is skipped over in up/down movements if it is inactive." - :type 'boolean - :group 'windmove) + :type 'boolean) (defcustom windmove-create-window nil "Whether movement off the edge of the frame creates a new window. @@ -147,7 +146,6 @@ If this variable is set to t, moving left from the leftmost window in a frame will create a new window on the left, and similarly for the other directions." :type 'boolean - :group 'windmove :version "27.1") ;; If your Emacs sometimes places an empty column between two adjacent @@ -157,11 +155,18 @@ directions." Measured in characters either horizontally or vertically; setting this to a value larger than 1 may be useful in getting around window- placement bugs in old versions of Emacs." - :type 'number - :group 'windmove) + :type 'number) (make-obsolete-variable 'windmove-window-distance-delta "no longer used." "27.1") +(defcustom windmove-allow-all-windows nil + "Whether the windmove commands are allowed to target all type of windows. +If this variable is set to non-nil, all windmove commmands will +ignore the `no-other-window' parameter applied by `display-buffer-alist' +or `set-window-parameter'." + :type 'boolean + :version "28.1") + ;; Note: ;; @@ -342,7 +347,8 @@ WINDOW must be a live window and defaults to the selected one. Optional ARG, if negative, means to use the right or bottom edge of WINDOW as reference position, instead of `window-point'; if positive, use the left or top edge of WINDOW as reference point." - (window-in-direction dir window nil arg windmove-wrap-around t)) + (window-in-direction dir window windmove-allow-all-windows + arg windmove-wrap-around t)) ;; Selects the window that's hopefully at the location returned by ;; `windmove-find-other-window', or screams if there's no window there. @@ -480,7 +486,6 @@ Default value of MODIFIERS is `shift'." (defcustom windmove-display-no-select nil "Whether the window should be selected after displaying the buffer in it." :type 'boolean - :group 'windmove :version "27.1") (defun windmove-display-in-direction (dir &optional arg) @@ -517,7 +522,7 @@ When `switch-to-buffer-obey-display-actions' is non-nil, ((eq dir 'same-window) (selected-window)) (t (window-in-direction - dir nil nil + dir nil windmove-allow-all-windows (and arg (prefix-numeric-value arg)) windmove-wrap-around 'nomini))))) (unless window @@ -606,8 +611,8 @@ With `M-0' prefix, delete the selected window and select the window at direction DIR. When `windmove-wrap-around' is non-nil, takes the window from the opposite side of the frame." - (let ((other-window (window-in-direction dir nil nil arg - windmove-wrap-around 'nomini))) + (let ((other-window (window-in-direction dir nil windmove-allow-all-windows + arg windmove-wrap-around 'nomini))) (cond ((null other-window) (user-error "No window %s from selected window" dir)) (t @@ -680,8 +685,8 @@ Default value of PREFIX is `C-x' and MODIFIERS is `shift'." "Swap the states of the selected window and the window at direction DIR. When `windmove-wrap-around' is non-nil, takes the window from the opposite side of the frame." - (let ((other-window (window-in-direction dir nil nil nil - windmove-wrap-around 'nomini))) + (let ((other-window (window-in-direction dir nil windmove-allow-all-windows + nil windmove-wrap-around 'nomini))) (cond ((or (null other-window) (window-minibuffer-p other-window)) (user-error "No window %s from selected window" dir)) (t @@ -761,8 +766,7 @@ See `windmove-default-keybindings' for more detail." (null val)) (set-default sym val)) :type windmove--default-keybindings-type - :version "28.1" - :group 'windmove) + :version "28.1") (defcustom windmove-display-default-keybindings nil "Default keybindings for windmove directional buffer display commands. @@ -780,8 +784,7 @@ See `windmove-display-default-keybindings' for more detail." (null val)) (set-default sym val)) :type windmove--default-keybindings-type - :version "28.1" - :group 'windmove) + :version "28.1") (defcustom windmove-delete-default-keybindings nil "Default keybindings for windmove directional window deletion commands. @@ -796,8 +799,7 @@ See `windmove-delete-default-keybindings' for more detail." (null val)) (set-default sym val)) :type windmove--default-keybindings-type - :version "28.1" - :group 'windmove) + :version "28.1") (defcustom windmove-swap-states-default-keybindings nil "Default keybindings for windmove's directional window swap-state commands. @@ -812,8 +814,7 @@ See `windmove-swap-states-default-keybindings' for more detail." (null val)) (set-default sym val)) :type windmove--default-keybindings-type - :version "28.1" - :group 'windmove) + :version "28.1") (provide 'windmove) -- cgit v1.2.3 From db106ea88b41e7b293f18a587cbe43685cb769a6 Mon Sep 17 00:00:00 2001 From: pillule Date: Wed, 16 Jun 2021 02:31:58 +0300 Subject: User option to choose a function triggered by windmove-create (bug#48917) * lisp/windmove.el (windmove-create-window): Add a defcustom choice. (windmove-do-window-select): Trigger custom functions, update the docstring. --- lisp/windmove.el | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'lisp/windmove.el') diff --git a/lisp/windmove.el b/lisp/windmove.el index ac146ab2dc7..3c1f20aa260 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -144,9 +144,18 @@ is inactive." "Whether movement off the edge of the frame creates a new window. If this variable is set to t, moving left from the leftmost window in a frame will create a new window on the left, and similarly for the other -directions." - :type 'boolean - :version "27.1") +directions. +This variable may also be a function to be called in this circumstance +by `windmove-do-window-select'. The function should accept then as +argument the DIRECTION targeted, an interactive ARG and a WINDOW +corresponding to the currently selected window. It should also return +a valid window that `windmove-do-window-select' will select, +or the symbol `no-select' to ignore that final selection." + :type '(choice + (const :tag "Don't create new windows" nil) + (const :tag "Create new windows" t) + (function :tag "Provide a function")) + :version "28.1") ;; If your Emacs sometimes places an empty column between two adjacent ;; windows, you may wish to set this delta to 2. @@ -356,19 +365,23 @@ use the left or top edge of WINDOW as reference point." "Move to the window at direction DIR as seen from WINDOW. DIR, ARG, and WINDOW are handled as by `windmove-find-other-window'. If no window is at direction DIR, an error is signaled. -If `windmove-create-window' is non-nil, try to create a new window +If `windmove-create-window' is a function, call that function with +DIR, ARG and WINDOW. If it is non-nil, try to create a new window in direction DIR instead." (let ((other-window (windmove-find-other-window dir arg window))) (when (and windmove-create-window (or (null other-window) (and (window-minibuffer-p other-window) (not (minibuffer-window-active-p other-window))))) - (setq other-window (split-window window nil dir))) + (setq other-window (if (functionp windmove-create-window) + (funcall windmove-create-window dir arg window) + (split-window window nil dir)))) (cond ((null other-window) (user-error "No window %s from selected window" dir)) ((and (window-minibuffer-p other-window) (not (minibuffer-window-active-p other-window))) (user-error "Minibuffer is inactive")) + ((eq other-window 'no-select)) (t (select-window other-window))))) -- cgit v1.2.3 From 45acbe6d622f807ff960e1c2fe92127188f57f68 Mon Sep 17 00:00:00 2001 From: Juri Linkov Date: Thu, 17 Jun 2021 22:53:57 +0300 Subject: Fix display-buffer-override-next-command for no-select case (bug#49057) * lisp/window.el (display-buffer-override-next-command): Separate 'postfun' from 'clearfun', so 'clearfun' resets 'display-buffer-overriding-action', whereas 'postfun' calls 'post-function' that can select the right window in 'post-command-hook'. * lisp/windmove.el (windmove-display-no-select): Add new choice 'ignore'. Improve docstring. (windmove-display-in-direction): Use new value 'ignore' of 'windmove-display-no-select'. Improve docstring. (windmove-display-left, windmove-display-up) (windmove-display-right, windmove-display-down): Mention 'windmove-display-no-select' in docstrings. --- lisp/windmove.el | 47 +++++++++++++++++++++++++++++++++++------------ lisp/window.el | 18 ++++++++++-------- 2 files changed, 45 insertions(+), 20 deletions(-) (limited to 'lisp/windmove.el') diff --git a/lisp/windmove.el b/lisp/windmove.el index 3c1f20aa260..f747c409431 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el @@ -497,8 +497,20 @@ Default value of MODIFIERS is `shift'." ;;; Directional window display and selection (defcustom windmove-display-no-select nil - "Whether the window should be selected after displaying the buffer in it." - :type 'boolean + "Whether the window should be selected after displaying the buffer in it. +If `nil', then the new window where the buffer is displayed will be selected. +If `ignore', then don't select a window: neither the new nor the old window, +thus allowing the next command to decide what window it selects. +Other non-nil values will reselect the old window that was selected before. + +The value of this variable can be overridden by the prefix arg of the +windmove-display-* commands that use `windmove-display-in-direction'. + +When `switch-to-buffer-obey-display-actions' is non-nil, +`switch-to-buffer' commands are also supported." + :type '(choice (const :tag "Select new window" nil) + (const :tag "Select old window" t) + (const :tag "Don't select a window" ignore)) :version "27.1") (defun windmove-display-in-direction (dir &optional arg) @@ -506,11 +518,17 @@ Default value of MODIFIERS is `shift'." The next buffer is the buffer displayed by the next command invoked immediately after this command (ignoring reading from the minibuffer). Create a new window if there is no window in that direction. -By default, select the window with a displayed buffer. -If prefix ARG is `C-u', reselect a previously selected window. -If `windmove-display-no-select' is non-nil, this command doesn't -select the window with a displayed buffer, and the meaning of -the prefix argument is reversed. + +By default, select the new window with a displayed buffer. +If `windmove-display-no-select' is `ignore', then allow the next command +to decide what window it selects. With other non-nil values of +`windmove-display-no-select', this function reselects +a previously selected old window. + +If prefix ARG is `C-u', reselect a previously selected old window. +If `windmove-display-no-select' is non-nil, the meaning of +the prefix argument is reversed and it selects the new window. + When `switch-to-buffer-obey-display-actions' is non-nil, `switch-to-buffer' commands are also supported." (let ((no-select (xor (consp arg) windmove-display-no-select))) @@ -542,35 +560,40 @@ When `switch-to-buffer-obey-display-actions' is non-nil, (setq window (split-window nil nil dir) type 'window)) (cons window type))) (lambda (old-window new-window) - (when (window-live-p (if no-select old-window new-window)) + (when (and (not (eq windmove-display-no-select 'ignore)) + (window-live-p (if no-select old-window new-window))) (select-window (if no-select old-window new-window)))) (format "[display-%s]" dir)))) ;;;###autoload (defun windmove-display-left (&optional arg) "Display the next buffer in window to the left of the current one. -See the logic of the prefix ARG in `windmove-display-in-direction'." +See the logic of the prefix ARG and `windmove-display-no-select' +in `windmove-display-in-direction'." (interactive "P") (windmove-display-in-direction 'left arg)) ;;;###autoload (defun windmove-display-up (&optional arg) "Display the next buffer in window above the current one. -See the logic of the prefix ARG in `windmove-display-in-direction'." +See the logic of the prefix ARG and `windmove-display-no-select' +in `windmove-display-in-direction'." (interactive "P") (windmove-display-in-direction 'up arg)) ;;;###autoload (defun windmove-display-right (&optional arg) "Display the next buffer in window to the right of the current one. -See the logic of the prefix ARG in `windmove-display-in-direction'." +See the logic of the prefix ARG and `windmove-display-no-select' +in `windmove-display-in-direction'." (interactive "P") (windmove-display-in-direction 'right arg)) ;;;###autoload (defun windmove-display-down (&optional arg) "Display the next buffer in window below the current one. -See the logic of the prefix ARG in `windmove-display-in-direction'." +See the logic of the prefix ARG and `windmove-display-no-select' +in `windmove-display-in-direction'." (interactive "P") (windmove-display-in-direction 'down arg)) diff --git a/lisp/window.el b/lisp/window.el index 6afc519e288..c0511bec4c4 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -8768,6 +8768,7 @@ to deactivate this overriding action." (new-window nil) (minibuffer-depth (minibuffer-depth)) (clearfun (make-symbol "clear-display-buffer-overriding-action")) + (postfun (make-symbol "post-display-buffer-override-next-command")) (action (lambda (buffer alist) (unless (> (minibuffer-depth) minibuffer-depth) (let* ((ret (funcall pre-function buffer alist)) @@ -8776,21 +8777,23 @@ to deactivate this overriding action." (setq new-window (window--display-buffer buffer window type alist)) ;; Reset display-buffer-overriding-action - ;; after the first buffer display action + ;; after the first display-buffer action (bug#39722). (funcall clearfun) - (setq post-function nil) new-window)))) (command this-command) (echofun (when echo (lambda () echo))) (exitfun (lambda () - (setcar display-buffer-overriding-action - (delq action (car display-buffer-overriding-action))) - (remove-hook 'post-command-hook clearfun) + (funcall clearfun) + (remove-hook 'post-command-hook postfun) (remove-hook 'prefix-command-echo-keystrokes-functions echofun) (when (functionp post-function) (funcall post-function old-window new-window))))) (fset clearfun + (lambda () + (setcar display-buffer-overriding-action + (delq action (car display-buffer-overriding-action))))) + (fset postfun (lambda () (unless (or ;; Remove the hook immediately @@ -8800,9 +8803,8 @@ to deactivate this overriding action." ;; adding the hook by the same command below. (eq this-command command)) (funcall exitfun)))) - ;; Reset display-buffer-overriding-action - ;; after the next command finishes - (add-hook 'post-command-hook clearfun) + ;; Call post-function after the next command finishes (bug#49057). + (add-hook 'post-command-hook postfun) (when echofun (add-hook 'prefix-command-echo-keystrokes-functions echofun)) (push action (car display-buffer-overriding-action)) -- cgit v1.2.3