diff options
Diffstat (limited to 'lisp/window.el')
-rw-r--r-- | lisp/window.el | 492 |
1 files changed, 346 insertions, 146 deletions
diff --git a/lisp/window.el b/lisp/window.el index a47a1216d10..7f1265b9ace 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -108,11 +108,14 @@ Return the buffer." ;; Return the buffer. buffer))) +;; Defined in help.el. +(defvar resize-temp-buffer-window-inhibit) + (defun temp-buffer-window-show (buffer &optional action) "Show temporary buffer BUFFER in a window. Return the window showing BUFFER. Pass ACTION as action argument to `display-buffer'." - (let (window frame) + (let (resize-temp-buffer-window-inhibit window) (with-current-buffer buffer (set-buffer-modified-p nil) (setq buffer-read-only t) @@ -130,9 +133,9 @@ to `display-buffer'." t window-combination-limit))) (setq window (display-buffer buffer action))) - (setq frame (window-frame window)) - (unless (eq frame (selected-frame)) - (raise-frame frame)) + ;; We used to raise the window's frame here. Do not do that + ;; since it would override an `inhibit-switch-frame' entry + ;; specified for the action alist used by `display-buffer'. (setq minibuffer-scroll-window window) (set-window-hscroll window 0) (with-selected-window window @@ -1514,21 +1517,11 @@ Emacs won't change the size of any window displaying that buffer, unless it has no other choice (like when deleting a neighboring window).") -(defun window--preservable-size (window &optional horizontal) - "Return height of WINDOW as `window-preserve-size' would preserve it. -Optional argument HORIZONTAL non-nil means to return the width of -WINDOW as `window-preserve-size' would preserve it." - (if horizontal - (window-body-width window t) - (+ (window-body-height window t) - (window-header-line-height window) - (window-mode-line-height window)))) - (defun window-preserve-size (&optional window horizontal preserve) - "Preserve height of window WINDOW. + "Preserve height of specified WINDOW's body. WINDOW must be a live window and defaults to the selected one. -Optional argument HORIZONTAL non-nil means preserve the width of -WINDOW. +Optional argument HORIZONTAL non-nil means to preserve the width +of WINDOW's body. PRESERVE t means to preserve the current height/width of WINDOW's body in frame and window resizing operations whenever possible. @@ -1545,21 +1538,15 @@ WINDOW as argument also removes the respective restraint. Other values of PRESERVE are reserved for future use." (setq window (window-normalize-window window t)) (let* ((parameter (window-parameter window 'window-preserved-size)) - (width (nth 1 parameter)) - (height (nth 2 parameter))) - (if horizontal - (set-window-parameter - window 'window-preserved-size - (list - (window-buffer window) - (and preserve (window--preservable-size window t)) - height)) - (set-window-parameter - window 'window-preserved-size - (list - (window-buffer window) - width - (and preserve (window--preservable-size window))))))) + (width (if horizontal + (and preserve (window-body-width window t)) + (nth 1 parameter))) + (height (if horizontal + (nth 2 parameter) + (and preserve (window-body-height window t))))) + (set-window-parameter + window 'window-preserved-size + (list (window-buffer window) width height)))) (defun window-preserved-size (&optional window horizontal) "Return preserved height of window WINDOW. @@ -1567,12 +1554,9 @@ WINDOW must be a live window and defaults to the selected one. Optional argument HORIZONTAL non-nil means to return preserved width of WINDOW." (setq window (window-normalize-window window t)) - (let* ((parameter (window-parameter window 'window-preserved-size)) - (buffer (nth 0 parameter)) - (width (nth 1 parameter)) - (height (nth 2 parameter))) - (when (eq buffer (window-buffer window)) - (if horizontal width height)))) + (let ((parameter (window-parameter window 'window-preserved-size))) + (when (eq (nth 0 parameter) (window-buffer window)) + (nth (if horizontal 1 2) parameter)))) (defun window--preserve-size (window horizontal) "Return non-nil when the height of WINDOW shall be preserved. @@ -1580,7 +1564,7 @@ Optional argument HORIZONTAL non-nil means to return non-nil when the width of WINDOW shall be preserved." (let ((size (window-preserved-size window horizontal))) (and (numberp size) - (= size (window--preservable-size window horizontal))))) + (= size (window-body-size window horizontal t))))) (defun window-safe-min-size (&optional window horizontal pixelwise) "Return safe minimum size of WINDOW. @@ -2504,15 +2488,23 @@ and no others." (defalias 'some-window 'get-window-with-predicate) +(defcustom display-buffer-avoid-small-windows nil + "If non-nil, windows that have fewer lines than this are avoided. +This is used by `get-lru-window'. The value is interpreted in units +of the frame's canonical line height, like `window-total-height' does." + :type '(choice (const nil) number) + :version "29.1" + :group 'windows) + (defun get-lru-window (&optional all-frames dedicated not-selected no-other) - "Return the least recently used window on frames specified by ALL-FRAMES. + "Return the least recently used window on frames specified by ALL-FRAMES. Return a full-width window if possible. A minibuffer window is never a candidate. A dedicated window is never a candidate unless DEDICATED is non-nil, so if all windows are dedicated, the value is nil. Avoid returning the selected window if possible. Optional argument NOT-SELECTED non-nil means never return the selected window. Optional argument NO-OTHER non-nil means to -never return a window whose 'no-other-window' parameter is +never return a window whose `no-other-window' parameter is non-nil. The following non-nil values of the optional argument ALL-FRAMES @@ -2529,15 +2521,23 @@ have special meanings: - A frame means consider all windows on that frame only. Any other value of ALL-FRAMES means consider all windows on the -selected frame and no others." - (let (best-window best-time second-best-window second-best-time time) - (dolist (window (window-list-1 nil 'nomini all-frames)) +selected frame and no others. + +`display-buffer-avoid-small-windows', if non-nil, is also taken into +consideration. Windows whose height is smaller that the value of that +variable will be avoided if larger windows are available." + (let ((windows (window-list-1 nil 'nomini all-frames)) + best-window best-time second-best-window second-best-time time) + (dolist (window windows) (when (and (or dedicated (not (window-dedicated-p window))) (or (not not-selected) (not (eq window (selected-window)))) (or (not no-other) (not (window-parameter window 'no-other-window)))) (setq time (window-use-time window)) (if (or (eq window (selected-window)) + (and display-buffer-avoid-small-windows + (< (window-height window) + display-buffer-avoid-small-windows)) (not (window-full-width-p window))) (when (or (not second-best-time) (< time second-best-time)) (setq second-best-time time) @@ -2554,7 +2554,7 @@ never a candidate unless DEDICATED is non-nil, so if all windows are dedicated, the value is nil. Optional argument NOT-SELECTED non-nil means never return the selected window. Optional argument NO-OTHER non-nil means to never return a window whose -'no-other-window' parameter is non-nil. +`no-other-window' parameter is non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -2590,7 +2590,7 @@ never a candidate unless DEDICATED is non-nil, so if all windows are dedicated, the value is nil. Optional argument NOT-SELECTED non-nil means never return the selected window. Optional argument NO-OTHER non-nil means to never return a window whose -'no-other-window' parameter is non-nil. +`no-other-window' parameter is non-nil. The following non-nil values of the optional argument ALL-FRAMES have special meanings: @@ -4181,8 +4181,8 @@ another live window on that frame to serve as its selected window. This option allows to control which window gets selected instead. -The possible choices are 'mru' (the default) to select the most -recently used window on that frame, and 'pos' to choose the +The possible choices are `mru' (the default) to select the most +recently used window on that frame, and `pos' to choose the window at the frame coordinates of point of the previously selected window. If this is nil, choose the frame's first window instead. A window with a non-nil `no-other-window' parameter is @@ -4594,7 +4594,9 @@ as well. In that case, if this option specifies a function, it will be called with the third argument nil. Under certain circumstances `switch-to-prev-buffer' may ignore -this option, for example, when there is only one buffer left." +this option, for example, when there is only one buffer left. + +Also see `switch-to-prev-buffer-skip-regexp'." :type '(choice (const :tag "Never" nil) (const :tag "This frame" this) @@ -4605,16 +4607,37 @@ this option, for example, when there is only one buffer left." :version "27.1" :group 'windows) +(defcustom switch-to-prev-buffer-skip-regexp nil + "Buffers that `switch-to-prev-buffer' and `switch-to-next-buffer' should skip. +The value can either be a regexp or a list of regexps. Buffers whose +names match these regexps are skipped by `switch-to-prev-buffer' +and `switch-to-next-buffer'. + +Also see `switch-to-prev-buffer-skip'." + :type '(choice regexp + (repeat regexp)) + :version "29.1" + :group 'windows) + (defun switch-to-prev-buffer-skip-p (skip window buffer &optional bury-or-kill) "Return non-nil if `switch-to-prev-buffer' should skip BUFFER. SKIP is a value derived from `switch-to-prev-buffer-skip', WINDOW the window `switch-to-prev-buffer' acts upon. Optional argument BURY-OR-KILL is passed unchanged by `switch-to-prev-buffer' and omitted in calls from `switch-to-next-buffer'." - (when skip - (if (functionp skip) - (funcall skip window buffer bury-or-kill) - (get-buffer-window buffer skip)))) + (or (and skip + (if (functionp skip) + (funcall skip window buffer bury-or-kill) + (get-buffer-window buffer skip))) + (and switch-to-prev-buffer-skip-regexp + (or (and (stringp switch-to-prev-buffer-skip-regexp) + (string-match-p switch-to-prev-buffer-skip-regexp + (buffer-name buffer))) + (and (consp switch-to-prev-buffer-skip-regexp) + (catch 'found + (dolist (regexp switch-to-prev-buffer-skip-regexp) + (when (string-match-p regexp (buffer-name buffer)) + (throw 'tag t))))))))) (defun switch-to-prev-buffer (&optional window bury-or-kill) "In WINDOW switch to previous buffer. @@ -4902,10 +4925,7 @@ the buffer `*scratch*', creating it if necessary." (setq frame (or frame (selected-frame))) (or (get-next-valid-buffer (nreverse (buffer-list frame)) buffer visible-ok frame) - (get-buffer "*scratch*") - (let ((scratch (get-buffer-create "*scratch*"))) - (set-buffer-major-mode scratch) - scratch))) + (get-scratch-buffer-create))) (defcustom frame-auto-hide-function #'iconify-frame "Function called to automatically hide frames. @@ -5023,7 +5043,11 @@ minibuffer window or is dedicated to its buffer." BUFFER-OR-NAME may be a buffer or the name of an existing buffer and defaults to the current buffer. -Interactively, prompt for the buffer. +Interactively, this command will prompt for the buffer name. A +prefix argument of 0 (zero) means that only windows in the +current terminal's frames will be deleted. Any other prefix +argument means that only windows in the current frame will be +deleted. The following non-nil values of the optional argument FRAME have special meanings: @@ -5060,7 +5084,21 @@ If the buffer specified by BUFFER-OR-NAME is shown in a minibuffer window, do nothing for that window. For any window that does not show that buffer, remove the buffer from that window's lists of previous and next buffers." - (interactive "bDelete windows on (buffer):\nP") + (interactive + (let ((frame (cond + ((and (numberp current-prefix-arg) + (zerop current-prefix-arg)) + 0) + (current-prefix-arg t)))) + (list (read-buffer "Delete windows on (buffer): " + nil nil + (lambda (buf) + (get-buffer-window + (if (consp buf) (car buf) buf) + (cond + ((null frame) t) + ((numberp frame) frame))))) + frame))) (let ((buffer (window-normalize-buffer buffer-or-name)) ;; Handle the "inverted" meaning of the FRAME argument wrt other ;; `window-list-1' based function. @@ -5120,6 +5158,14 @@ all window-local buffer lists." :version "27.1" :group 'windows) +(defun window--quit-restore-select-window (window) + "Select WINDOW after having quit another one. +Do not select an inactive minibuffer window." + (when (and (window-live-p window) + (or (not (window-minibuffer-p window)) + (minibuffer-window-active-p window))) + (select-window window))) + (defun quit-restore-window (&optional window bury-or-kill) "Quit WINDOW and deal with its buffer. WINDOW must be a live window and defaults to the selected one. @@ -5133,7 +5179,7 @@ parameter to nil. See Info node `(elisp) Quitting Windows' for more details. If WINDOW's dedicated flag is t, try to delete WINDOW. If it -equals the value 'side', restore that value when WINDOW is not +equals the value `side', restore that value when WINDOW is not deleted. Optional second argument BURY-OR-KILL tells how to proceed with @@ -5158,6 +5204,7 @@ nil means to not handle the buffer in a particular way. This (setq window (window-normalize-window window t)) (let* ((buffer (window-buffer window)) (quit-restore (window-parameter window 'quit-restore)) + (quit-restore-2 (nth 2 quit-restore)) (prev-buffer (catch 'prev-buffer (dolist (buf (window-prev-buffers window)) (unless (eq (car buf) buffer) @@ -5169,15 +5216,13 @@ nil means to not handle the buffer in a particular way. This ((and dedicated (not (eq dedicated 'side)) (window--delete window 'dedicated (eq bury-or-kill 'kill))) ;; If the previously selected window is still alive, select it. - (when (window-live-p (nth 2 quit-restore)) - (select-window (nth 2 quit-restore)))) + (window--quit-restore-select-window quit-restore-2)) ((and (not prev-buffer) (eq (nth 1 quit-restore) 'tab) (eq (nth 3 quit-restore) buffer)) (tab-bar-close-tab) ;; If the previously selected window is still alive, select it. - (when (window-live-p (nth 2 quit-restore)) - (select-window (nth 2 quit-restore)))) + (window--quit-restore-select-window quit-restore-2)) ((and (not prev-buffer) (or (eq (nth 1 quit-restore) 'frame) (and (eq (nth 1 quit-restore) 'window) @@ -5189,8 +5234,7 @@ nil means to not handle the buffer in a particular way. This ;; Delete WINDOW if possible. (window--delete window nil (eq bury-or-kill 'kill))) ;; If the previously selected window is still alive, select it. - (when (window-live-p (nth 2 quit-restore)) - (select-window (nth 2 quit-restore)))) + (window--quit-restore-select-window quit-restore-2)) ((and (listp (setq quad (nth 1 quit-restore))) (buffer-live-p (car quad)) (eq (nth 3 quit-restore) buffer)) @@ -5234,8 +5278,8 @@ nil means to not handle the buffer in a particular way. This ;; Reset the quit-restore parameter. (set-window-parameter window 'quit-restore nil) ;; Select old window. - (when (window-live-p (nth 2 quit-restore)) - (select-window (nth 2 quit-restore)))) + ;; If the previously selected window is still alive, select it. + (window--quit-restore-select-window quit-restore-2)) (t ;; Show some other buffer in WINDOW and reset the quit-restore ;; parameter. @@ -5248,8 +5292,8 @@ nil means to not handle the buffer in a particular way. This (when (eq dedicated 'side) (set-window-dedicated-p window 'side)) (window--delete window nil (eq bury-or-kill 'kill)) - (when (window-live-p (nth 2 quit-restore)) - (select-window (nth 2 quit-restore)))))) + ;; If the previously selected window is still alive, select it. + (window--quit-restore-select-window quit-restore-2)))) ;; Deal with the buffer. (cond @@ -5714,12 +5758,12 @@ right, if any." ;;; Balancing windows. ;; The following routine uses the recycled code from an old version of -;; `window--resize-child-windows'. It's not very pretty, but coding it the way the -;; new `window--resize-child-windows' code does would hardly make it any shorter or -;; more readable (FWIW we'd need three loops - one to calculate the -;; minimum sizes per window, one to enlarge or shrink windows until the -;; new parent-size matches, and one where we shrink the largest/enlarge -;; the smallest window). +;; `window--resize-child-windows'. It's not very pretty, but coding it +;; the way the new `window--resize-child-windows' code does would hardly +;; make it any shorter or more readable (FWIW we'd need three loops - +;; one to calculate the minimum sizes per window, one to enlarge or +;; shrink windows until the new parent-size matches, and one where we +;; shrink the largest/enlarge the smallest window). (defun balance-windows-2 (window horizontal) "Subroutine of `balance-windows-1'. WINDOW must be a vertical combination (horizontal if HORIZONTAL @@ -5730,9 +5774,10 @@ is non-nil)." (first (window-child window)) (sub first) (number-of-children 0) + (rest 0) (parent-size (window-new-pixel window)) (total-sum parent-size) - failed size sub-total sub-delta sub-amount rest) + failed size sub-total sub-delta sub-amount) (while sub (if (window-size-fixed-p sub horizontal) (progn @@ -7257,11 +7302,15 @@ Return WINDOW if BUFFER and WINDOW are live." (inhibit-modification-hooks t)) (funcall (cdr (assq 'body-function alist)) window))) - (let ((quit-restore (window-parameter window 'quit-restore)) - (height (cdr (assq 'window-height alist))) - (width (cdr (assq 'window-width alist))) - (size (cdr (assq 'window-size alist))) - (preserve-size (cdr (assq 'preserve-size alist)))) + (let* ((frame (window-frame window)) + (quit-restore (window-parameter window 'quit-restore)) + (window-height (assq 'window-height alist)) + (height (cdr window-height)) + (window-width (assq 'window-width alist)) + (width (cdr window-width)) + (window-size (assq 'window-size alist)) + (size (cdr window-size)) + (preserve-size (cdr (assq 'preserve-size alist)))) (cond ((or (eq type 'frame) (and (eq (car quit-restore) 'same) @@ -7272,29 +7321,43 @@ Return WINDOW if BUFFER and WINDOW are live." ;; Adjust size of frame if asked for. We probably should do ;; that only for a single window frame. (cond - ((not size)) + ((not size) + (when window-size + (setq resize-temp-buffer-window-inhibit t))) ((consp size) - (let ((width (car size)) - (height (cdr size)) - (frame (window-frame window))) - (when (and (numberp width) (numberp height)) - (set-frame-height - frame (+ (frame-height frame) - (- height (window-total-height window)))) - (set-frame-width - frame (+ (frame-width frame) - (- width (window-total-width window))))))) - ((functionp size) - (ignore-errors (funcall size window))))) + ;; Modifying the parameters of a newly created frame might + ;; not work everywhere, but then `temp-buffer-resize-mode' + ;; will certainly fail in a similar fashion. + (if (eq (car size) 'body-chars) + (let ((width (+ (frame-text-width frame) + (* (frame-char-width frame) (cadr size)) + (- (window-body-width window t)))) + (height (+ (frame-text-height frame) + (* (frame-char-height frame) (cddr size)) + (- (window-body-height window t))))) + (modify-frame-parameters + frame `((height . (text-pixels . ,height)) + (width . (text-pixels . ,width))))) + (let ((width (- (+ (frame-width frame) (car size)) + (window-total-width window))) + (height (- (+ (frame-height frame) (cdr size)) + (window-total-height window)))) + (modify-frame-parameters + frame `((height . ,height) (width . ,width))))) + (setq resize-temp-buffer-window-inhibit t)) + ((functionp size) + (ignore-errors (funcall size window)) + (setq resize-temp-buffer-window-inhibit t)))) ((or (eq type 'window) (and (eq (car quit-restore) 'same) (eq (nth 1 quit-restore) 'window))) ;; A window that never showed another buffer but BUFFER ever - ;; since it was created on an existing frame. - ;; - ;; Adjust width and/or height of window if asked for. + ;; since it was created on an existing frame. Adjust its width + ;; and/or height if asked for. (cond - ((not height)) + ((not height) + (when window-height + (setq resize-temp-buffer-window-inhibit 'vertical))) ((numberp height) (let* ((new-height (if (integerp height) @@ -7305,12 +7368,23 @@ Return WINDOW if BUFFER and WINDOW are live." (delta (- new-height (window-total-height window)))) (when (and (window--resizable-p window delta nil 'safe) (window-combined-p window)) - (window-resize window delta nil 'safe)))) - ((functionp height) - (ignore-errors (funcall height window)))) + (window-resize window delta nil 'safe))) + (setq resize-temp-buffer-window-inhibit 'vertical)) + ((and (consp height) (eq (car height) 'body-lines)) + (let* ((delta (- (* (frame-char-height frame) (cdr height)) + (window-body-height window t)))) + (and (window--resizable-p window delta nil 'safe nil nil nil t) + (window-combined-p window) + (window-resize window delta nil 'safe t))) + (setq resize-temp-buffer-window-inhibit 'vertical)) + ((functionp height) + (ignore-errors (funcall height window)) + (setq resize-temp-buffer-window-inhibit 'vertical))) ;; Adjust width of window if asked for. (cond - ((not width)) + ((not width) + (when window-width + (setq resize-temp-buffer-window-inhibit 'horizontal))) ((numberp width) (let* ((new-width (if (integerp width) @@ -7321,13 +7395,24 @@ Return WINDOW if BUFFER and WINDOW are live." (delta (- new-width (window-total-width window)))) (when (and (window--resizable-p window delta t 'safe) (window-combined-p window t)) - (window-resize window delta t 'safe)))) + (window-resize window delta t 'safe))) + (setq resize-temp-buffer-window-inhibit 'horizontal)) + ((and (consp width) (eq (car width) 'body-columns)) + (let* ((delta (- (* (frame-char-width frame) (cdr width)) + (window-body-width window t)))) + (and (window--resizable-p window delta t 'safe nil nil nil t) + (window-combined-p window t) + (window-resize window delta t 'safe t))) + (setq resize-temp-buffer-window-inhibit 'horizontal)) ((functionp width) - (ignore-errors (funcall width window)))) + (ignore-errors (funcall width window)) + (setq resize-temp-buffer-window-inhibit 'horizontal))) + ;; Preserve window size if asked for. (when (consp preserve-size) (window-preserve-size window t (car preserve-size)) (window-preserve-size window nil (cdr preserve-size))))) + ;; Assign any window parameters specified. (let ((parameters (cdr (assq 'window-parameters alist)))) (dolist (parameter parameters) @@ -7366,6 +7451,7 @@ The actual non-nil value of this variable will be copied to the (const display-buffer-pop-up-window) (const display-buffer-same-window) (const display-buffer-pop-up-frame) + (const display-buffer-full-frame) (const display-buffer-in-child-frame) (const display-buffer-below-selected) (const display-buffer-at-bottom) @@ -7415,9 +7501,9 @@ Its value takes effect before processing the ACTION argument of If non-nil, this is an alist of elements (CONDITION . ACTION), where: - CONDITION is either a regexp matching buffer names, or a - function that takes two arguments - a buffer name and the - ACTION argument of `display-buffer' - and returns a boolean. + CONDITION is passed to `buffer-match-p', along with the buffer + that is to be displayed and the ACTION argument of + `display-buffer', to check if ACTION should be used. ACTION is a cons cell (FUNCTIONS . ALIST), where FUNCTIONS is an action function or a list of action functions and ALIST is an @@ -7470,22 +7556,16 @@ all fail. It should never be set by programs or users. See `display-buffer'.") (put 'display-buffer-fallback-action 'risky-local-variable t) -(defun display-buffer-assq-regexp (buffer-name alist action) - "Retrieve ALIST entry corresponding to BUFFER-NAME. -This returns the cdr of the alist entry ALIST if either its key -is a string that matches BUFFER-NAME, as reported by -`string-match-p'; or if the key is a function that returns -non-nil when called with three arguments: the ALIST key, -BUFFER-NAME and ACTION. ACTION should have the form of the -action argument passed to `display-buffer'." +(defun display-buffer-assq-regexp (buffer-or-name alist action) + "Retrieve ALIST entry corresponding to buffer specified by BUFFER-OR-NAME. +This returns the cdr of the alist entry ALIST if the entry's +key (its car) and BUFFER-OR-NAME satisfy `buffer-match-p', using +the key as CONDITION argument of `buffer-match-p'. ACTION should +have the form of the action argument passed to `display-buffer'." (catch 'match (dolist (entry alist) - (let ((key (car entry))) - (when (or (and (stringp key) - (string-match-p key buffer-name)) - (and (functionp key) - (funcall key buffer-name action))) - (throw 'match (cdr entry))))))) + (when (buffer-match-p (car entry) buffer-or-name action) + (throw 'match (cdr entry)))))) (defvar display-buffer--same-window-action '(display-buffer-same-window @@ -7518,6 +7598,7 @@ to an expression containing one of these \"action\" functions: `display-buffer-use-least-recent-window' -- Try to avoid re-using windows that have recently been switched to. `display-buffer-pop-up-window' -- Pop up a new window. + `display-buffer-full-frame' -- Delete other windows and use the full frame. `display-buffer-below-selected' -- Use or pop up a window below the selected one. `display-buffer-at-bottom' -- Use or pop up a window at the @@ -7530,7 +7611,7 @@ to an expression containing one of these \"action\" functions: For instance: - (setq display-buffer-alist '((\".*\" display-buffer-at-bottom))) + (setq display-buffer-alist \\='((\".*\" display-buffer-at-bottom))) Buffer display can be further customized to a very high degree; the rest of this docstring explains some of the many @@ -7570,6 +7651,9 @@ Action alist entries are: window from being used for display. `inhibit-switch-frame' -- A non-nil value prevents any frame used for showing the buffer from being raised or selected. + Note that a window manager may still raise a new frame and + give it focus, effectively overriding the value specified + here. `reusable-frames' -- The value specifies the set of frames to search for a window that already displays the buffer. Possible values are nil (the selected frame), t (any live @@ -7579,20 +7663,33 @@ Action alist entries are: frame parameters to give a new frame, if one is created. `window-height' -- The value specifies the desired height of the window chosen and is either an integer (the total height of - the window), a floating point number (the fraction of its - total height with respect to the total height of the frame's - root window) or a function to be called with one argument - - the chosen window. The function is supposed to adjust the - height of the window; its return value is ignored. Suitable - functions are `shrink-window-if-larger-than-buffer' and - `fit-window-to-buffer'. + the window specified in frame lines), a floating point + number (the fraction of its total height with respect to the + total height of the frame's root window), a cons cell whose + car is `body-lines' and whose cdr is an integer that + specifies the height of the window's body in frame lines, or + a function to be called with one argument - the chosen + window. That function is supposed to adjust the height of + the window. Suitable functions are `fit-window-to-buffer' + and `shrink-window-if-larger-than-buffer'. `window-width' -- The value specifies the desired width of the window chosen and is either an integer (the total width of - the window), a floating point number (the fraction of its - total width with respect to the width of the frame's root - window) or a function to be called with one argument - the - chosen window. The function is supposed to adjust the width - of the window; its return value is ignored. + the window specified in frame lines), a floating point + number (the fraction of its total width with respect to the + width of the frame's root window), a cons cell whose car is + `body-columns' and whose cdr is an integer that specifies the + width of the window's body in frame columns, or a function to + be called with one argument - the chosen window. That + function is supposed to adjust the width of the window. + `window-size' -- This entry is only useful for windows appearing + alone on their frame and specifies the desired size of that + window either as a cons of integers (the total width and + height of the window on that frame), a cons cell whose car is + `body-chars' and whose cdr is a cons of integers (the desired + width and height of the window's body in columns and lines of + its frame), or a function to be called with one argument - + the chosen window. That function is supposed to adjust the + size of the frame. `preserve-size' -- The value should be either (t . nil) to preserve the width of the chosen window, (nil . t) to preserve its height or (t . t) to preserve its height and @@ -7608,9 +7705,9 @@ Action alist entries are: to fill the window body with some contents that might depend on dimensions of the displayed window. -The entries `window-height', `window-width' and `preserve-size' -are applied only when the window used for displaying the buffer -never showed another buffer before. +The entries `window-height', `window-width', `window-size' and +`preserve-size' are applied only when the window used for +displaying the buffer never showed another buffer before. The ACTION argument can also have a non-nil and non-list value. This means to display the buffer in a window other than the @@ -7638,7 +7735,7 @@ specified by the ACTION argument." ;; Otherwise, use the defined actions. (let* ((user-action (display-buffer-assq-regexp - (buffer-name buffer) display-buffer-alist action)) + buffer display-buffer-alist action)) (special-action (display-buffer--special-action buffer)) ;; Extra actions from the arguments to this function: (extra-action @@ -7735,6 +7832,23 @@ indirectly called by the latter." (window-dedicated-p)) (window--display-buffer buffer (selected-window) 'reuse alist))) +(defun display-buffer-full-frame (buffer alist) + "Display BUFFER in the current frame, taking the entire frame. +ALIST is an association list of action symbols and values. See +Info node `(elisp) Buffer Display Action Alists' for details of +such alists. + +This is an action function for buffer display, see Info +node `(elisp) Buffer Display Action Functions'. It should be +called only by `display-buffer' or a function directly or +indirectly called by the latter." + (when-let ((window (or (display-buffer-reuse-window buffer alist) + (display-buffer-same-window buffer alist) + (display-buffer-pop-up-window buffer alist) + (display-buffer-use-some-window buffer alist)))) + (delete-other-windows window) + window)) + (defun display-buffer--maybe-same-window (buffer alist) "Conditionally display BUFFER in the selected window. ALIST is an association list of action symbols and values. See @@ -8531,6 +8645,14 @@ currently selected window; otherwise it will be displayed in another window." (pop-to-buffer buffer display-buffer--same-window-action norecord)) +(defcustom display-comint-buffer-action display-buffer--same-window-action + "`display-buffer' action for displaying comint buffers." + :type display-buffer--action-custom-type + :risky t + :version "29.1" + :group 'windows + :group 'comint) + (defun read-buffer-to-switch (prompt) "Read the name of a buffer to switch to, prompting with PROMPT. Return the name of the buffer as a string. @@ -8541,7 +8663,7 @@ from the list of completions and default values." (let ((rbts-completion-table (internal-complete-buffer-except))) (minibuffer-with-setup-hook (lambda () - (setq minibuffer-completion-table rbts-completion-table) + (setq-local minibuffer-completion-table rbts-completion-table) ;; Since rbts-completion-table is built dynamically, we ;; can't just add it to the default value of ;; icomplete-with-completion-tables, so we add it @@ -8560,12 +8682,13 @@ If BUFFER-OR-NAME is nil, return the buffer returned by `other-buffer'. Else, if a buffer specified by BUFFER-OR-NAME exists, return that buffer. If no such buffer exists, create a buffer with the name BUFFER-OR-NAME and return that buffer." - (if buffer-or-name - (or (get-buffer buffer-or-name) - (let ((buffer (get-buffer-create buffer-or-name))) - (set-buffer-major-mode buffer) - buffer)) - (other-buffer))) + (pcase buffer-or-name + ('nil (other-buffer)) + ("*scratch*" (get-scratch-buffer-create)) + (_ (or (get-buffer buffer-or-name) + (let ((buffer (get-buffer-create buffer-or-name))) + (set-buffer-major-mode buffer) + buffer))))) (defcustom switch-to-buffer-preserve-window-point t "If non-nil, `switch-to-buffer' tries to preserve `window-point'. @@ -9970,6 +10093,11 @@ When point is already on that position, then signal an error." (defun scroll-up-command (&optional arg) "Scroll text of selected window upward ARG lines; or near full screen if no ARG. +Interactively, giving this command a numerical prefix will scroll +up by that many lines (and down by that many lines if the number +is negative). Without a prefix, scroll up by a full screen. +If given a `C-u -' prefix, scroll a full page down instead. + If `scroll-error-top-bottom' is non-nil and `scroll-up' cannot scroll window further, move cursor to the bottom line. When point is already on that position, then signal an error. @@ -10002,6 +10130,11 @@ If ARG is the atom `-', scroll downward by nearly full screen." (defun scroll-down-command (&optional arg) "Scroll text of selected window down ARG lines; or near full screen if no ARG. +Interactively, giving this command a numerical prefix will scroll +down by that many lines (and up by that many lines if the number +is negative). Without a prefix, scroll down by a full screen. +If given a `C-u -' prefix, scroll a full page up instead. + If `scroll-error-top-bottom' is non-nil and `scroll-down' cannot scroll window further, move cursor to the top line. When point is already on that position, then signal an error. @@ -10032,6 +10165,24 @@ If ARG is the atom `-', scroll upward by nearly full screen." (put 'scroll-down-command 'scroll-command t) +(defun scroll-other-window (&optional lines) + "Scroll next window upward LINES lines; or near full screen if no ARG. +See `scroll-up-command' for details." + (interactive "P") + (with-selected-window (other-window-for-scrolling) + (funcall (or (command-remapping #'scroll-up-command) + #'scroll-up-command) + lines))) + +(defun scroll-other-window-down (&optional lines) + "Scroll next window downward LINES lines; or near full screen if no ARG. +See `scroll-down-command' for details." + (interactive "P") + (with-selected-window (other-window-for-scrolling) + (funcall (or (command-remapping #'scroll-down-command) + #'scroll-down-command) + lines))) + ;;; Scrolling commands which scroll a line instead of full screen. (defun scroll-up-line (&optional arg) @@ -10419,6 +10570,55 @@ displaying that processes's buffer." (put 'shrink-window-horizontally 'repeat-map 'resize-window-repeat-map) (put 'shrink-window 'repeat-map 'resize-window-repeat-map) +(defun window-char-pixel-width (&optional window face) + "Return average character width for the font of FACE used in WINDOW. +WINDOW must be a live window and defaults to the selected one. + +If FACE is nil or omitted, the default face is used. If FACE is +remapped (see `face-remapping-alist'), the function returns the +information for the remapped face." + (with-selected-window (window-normalize-window window t) + (let* ((info (font-info (face-font (or face 'default)))) + (width (aref info 11))) + (if (> width 0) + width + (aref info 10))))) + +(defun window-char-pixel-height (&optional window face) + "Return character height for the font of FACE used in WINDOW. +WINDOW must be a live window and defaults to the selected one. + +If FACE is nil or omitted, the default face is used. If FACE is +remapped (see `face-remapping-alist'), the function returns the +information for the remapped face." + (with-selected-window (window-normalize-window window t) + (aref (font-info (face-font (or face 'default))) 3))) + +(defun window-max-characters-per-line (&optional window face) + "Return the number of characters that can be displayed on one line in WINDOW. +WINDOW must be a live window and defaults to the selected one. + +The character width of FACE is used for the calculation. If FACE +is nil or omitted, the default face is used. If FACE is +remapped (see `face-remapping-alist'), the function uses the +remapped face. + +This function is different from `window-body-width' in two +ways. First, it accounts for the portions of the line reserved +for the continuation glyph. Second, it accounts for the size of +the font, which may have been adjusted, e.g., using +`text-scale-increase')." + (with-selected-window (window-normalize-window window t) + (let* ((window-width (window-body-width window t)) + (font-width (window-char-pixel-width window face)) + (ncols (/ window-width font-width))) + (if (and (display-graphic-p) + overflow-newline-into-fringe + (/= (frame-parameter nil 'left-fringe) 0) + (/= (frame-parameter nil 'right-fringe) 0)) + ncols + (1- ncols))))) + (provide 'window) ;;; window.el ends here |