diff options
| -rw-r--r-- | etc/NEWS | 12 | ||||
| -rw-r--r-- | lisp/windmove.el | 108 |
2 files changed, 119 insertions, 1 deletions
| @@ -304,6 +304,18 @@ back, customize follow-hide-ghost-cursors to nil. | |||
| 304 | 304 | ||
| 305 | ** Windmove | 305 | ** Windmove |
| 306 | 306 | ||
| 307 | *** Windmove supports directional window display and selection. | ||
| 308 | The new command windmove-display-default-keybindings binds default | ||
| 309 | keys with provided modifiers (by default, shift-meta) to the commands | ||
| 310 | that display the next buffer in the window at the specified direction. | ||
| 311 | This is like windmove-default-keybindings that binds keys to commands | ||
| 312 | that select the window in the specified direction, but additionally it | ||
| 313 | displays the buffer from the next command in that window. For example, | ||
| 314 | 'S-M-right C-h i' displays the *Info* buffer in the right window, | ||
| 315 | creating the window if necessary. A special key can be customized to | ||
| 316 | display the buffer in the same window, for example, 'S-M-0 C-h e' | ||
| 317 | displays the *Messages* buffer in the same window. | ||
| 318 | |||
| 307 | *** windmove-create-window when non-nil makes a new window on moving off | 319 | *** windmove-create-window when non-nil makes a new window on moving off |
| 308 | the edge of the frame. | 320 | the edge of the frame. |
| 309 | 321 | ||
diff --git a/lisp/windmove.el b/lisp/windmove.el index c38524fede6..898f87e2dbf 100644 --- a/lisp/windmove.el +++ b/lisp/windmove.el | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | ;;; windmove.el --- directional window-selection routines | 1 | ;;; windmove.el --- directional window-selection routines -*- lexical-binding:t -*- |
| 2 | ;; | 2 | ;; |
| 3 | ;; Copyright (C) 1998-2018 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1998-2018 Free Software Foundation, Inc. |
| 4 | ;; | 4 | ;; |
| @@ -571,6 +571,112 @@ Default value of MODIFIERS is `shift'." | |||
| 571 | (global-set-key (vector (append modifiers '(up))) 'windmove-up) | 571 | (global-set-key (vector (append modifiers '(up))) 'windmove-up) |
| 572 | (global-set-key (vector (append modifiers '(down))) 'windmove-down)) | 572 | (global-set-key (vector (append modifiers '(down))) 'windmove-down)) |
| 573 | 573 | ||
| 574 | ;;; Directional window display and selection | ||
| 575 | |||
| 576 | (defcustom windmove-display-no-select nil | ||
| 577 | "Whether the window should be selected after displaying the buffer in it." | ||
| 578 | :type 'boolean | ||
| 579 | :group 'windmove | ||
| 580 | :version "27.1") | ||
| 581 | |||
| 582 | (defun windmove-display-in-direction (dir &optional arg) | ||
| 583 | "Display the next buffer in the window at direction DIR. | ||
| 584 | The next buffer is the buffer displayed by the next command invoked | ||
| 585 | immediately after this command (ignoring reading from the minibuffer). | ||
| 586 | Create a new window if there is no window in that direction. | ||
| 587 | By default, select the window with a displayed buffer. | ||
| 588 | If prefix ARG is `C-u', reselect a previously selected window. | ||
| 589 | If `windmove-display-no-select' is non-nil, this command doesn't | ||
| 590 | select the window with a displayed buffer, and the meaning of | ||
| 591 | the prefix argument is reversed." | ||
| 592 | (let* ((no-select (not (eq (consp arg) windmove-display-no-select))) ; xor | ||
| 593 | (old-window (or (minibuffer-selected-window) (selected-window))) | ||
| 594 | (new-window) | ||
| 595 | (minibuffer-depth (minibuffer-depth)) | ||
| 596 | (action display-buffer-overriding-action) | ||
| 597 | (command this-command) | ||
| 598 | (clearfun (make-symbol "clear-display-buffer-overriding-action")) | ||
| 599 | (exitfun | ||
| 600 | (lambda () | ||
| 601 | (setq display-buffer-overriding-action action) | ||
| 602 | (when (window-live-p (if no-select old-window new-window)) | ||
| 603 | (select-window (if no-select old-window new-window))) | ||
| 604 | (remove-hook 'post-command-hook clearfun)))) | ||
| 605 | (fset clearfun | ||
| 606 | (lambda () | ||
| 607 | (unless (or | ||
| 608 | ;; Remove the hook immediately | ||
| 609 | ;; after exiting the minibuffer. | ||
| 610 | (> (minibuffer-depth) minibuffer-depth) | ||
| 611 | ;; But don't remove immediately after | ||
| 612 | ;; adding the hook by the same command below. | ||
| 613 | (eq this-command command)) | ||
| 614 | (funcall exitfun)))) | ||
| 615 | (add-hook 'post-command-hook clearfun) | ||
| 616 | (push (lambda (buffer alist) | ||
| 617 | (unless (> (minibuffer-depth) minibuffer-depth) | ||
| 618 | (let ((window (if (eq dir 'same-window) | ||
| 619 | (selected-window) | ||
| 620 | (window-in-direction | ||
| 621 | dir nil nil | ||
| 622 | (and arg (prefix-numeric-value arg)) | ||
| 623 | windmove-wrap-around))) | ||
| 624 | (type 'reuse)) | ||
| 625 | (unless window | ||
| 626 | (setq window (split-window nil nil dir) type 'window)) | ||
| 627 | (setq new-window (window--display-buffer buffer window type alist))))) | ||
| 628 | display-buffer-overriding-action) | ||
| 629 | (message "[display-%s]" dir))) | ||
| 630 | |||
| 631 | ;;;###autoload | ||
| 632 | (defun windmove-display-left (&optional arg) | ||
| 633 | "Display the next buffer in window to the left of the current one. | ||
| 634 | See the logic of the prefix ARG in `windmove-display-in-direction'." | ||
| 635 | (interactive "P") | ||
| 636 | (windmove-display-in-direction 'left arg)) | ||
| 637 | |||
| 638 | ;;;###autoload | ||
| 639 | (defun windmove-display-up (&optional arg) | ||
| 640 | "Display the next buffer in window above the current one. | ||
| 641 | See the logic of the prefix ARG in `windmove-display-in-direction'." | ||
| 642 | (interactive "P") | ||
| 643 | (windmove-display-in-direction 'up arg)) | ||
| 644 | |||
| 645 | ;;;###autoload | ||
| 646 | (defun windmove-display-right (&optional arg) | ||
| 647 | "Display the next buffer in window to the right of the current one. | ||
| 648 | See the logic of the prefix ARG in `windmove-display-in-direction'." | ||
| 649 | (interactive "P") | ||
| 650 | (windmove-display-in-direction 'right arg)) | ||
| 651 | |||
| 652 | ;;;###autoload | ||
| 653 | (defun windmove-display-down (&optional arg) | ||
| 654 | "Display the next buffer in window below the current one. | ||
| 655 | See the logic of the prefix ARG in `windmove-display-in-direction'." | ||
| 656 | (interactive "P") | ||
| 657 | (windmove-display-in-direction 'down arg)) | ||
| 658 | |||
| 659 | ;;;###autoload | ||
| 660 | (defun windmove-display-same-window (&optional arg) | ||
| 661 | "Display the next buffer in the same window." | ||
| 662 | (interactive "P") | ||
| 663 | (windmove-display-in-direction 'same-window arg)) | ||
| 664 | |||
| 665 | ;;;###autoload | ||
| 666 | (defun windmove-display-default-keybindings (&optional modifiers) | ||
| 667 | "Set up keybindings for directional buffer display. | ||
| 668 | Keys are bound to commands that display the next buffer in the specified | ||
| 669 | direction. Keybindings are of the form MODIFIERS-{left,right,up,down}, | ||
| 670 | where MODIFIERS is either a list of modifiers or a single modifier. | ||
| 671 | Default value of MODIFIERS is `shift-meta'." | ||
| 672 | (interactive) | ||
| 673 | (unless modifiers (setq modifiers '(shift meta))) | ||
| 674 | (unless (listp modifiers) (setq modifiers (list modifiers))) | ||
| 675 | (global-set-key (vector (append modifiers '(left))) 'windmove-display-left) | ||
| 676 | (global-set-key (vector (append modifiers '(right))) 'windmove-display-right) | ||
| 677 | (global-set-key (vector (append modifiers '(up))) 'windmove-display-up) | ||
| 678 | (global-set-key (vector (append modifiers '(down))) 'windmove-display-down) | ||
| 679 | (global-set-key (vector (append modifiers '(?0))) 'windmove-display-same-window)) | ||
| 574 | 680 | ||
| 575 | (provide 'windmove) | 681 | (provide 'windmove) |
| 576 | 682 | ||