From f92c5f91099a448ff39a46ecbc3fc44a3e56239d Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Tue, 2 Nov 2010 18:04:40 +0100 Subject: [PATCH] Provide new semantics for cdr of `not-this-window' and `not-this-frame' specifiers when passed as argument to `display-buffer'. Use buffer display specifiers in compilation functions. * window.el (display-buffer-names): Describe `not-this-window' and `not-this-frame' specifiers in doc-string. (display-buffer-in-lru-buffer-window) (display-buffer-in-lru-window, display-buffer-in-new-window): Handle `not-this-window' and `not-this-frame' specifiers when their cdr specifies a window or a frame. (display-buffer): Explain in doc-string that the cdr of the `not-this-window' and `not-this-frame' specifiers argument can name a window. * progmodes/compile.el (compilation-start): When displaying outbuf directly pass height parameters. (compilation-goto-locus): Use specifiers in display-buffer and pop-to-buffer calls. Simplify. (compilation-find-file): Use specifiers in display-buffer calls. * windows.texi (Displaying Buffers): Describe special handling of `not-this-window' and `not-this-frame' specifiers for `display-buffer'. --- doc/lispref/ChangeLog | 6 ++ doc/lispref/windows.texi | 7 ++ lisp/ChangeLog | 18 +++++ lisp/progmodes/compile.el | 148 ++++++++++++++++++-------------------- lisp/window.el | 66 +++++++++++++---- 5 files changed, 154 insertions(+), 91 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index d0d02a05958..95e7f92c188 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,9 @@ +2010-11-02 Martin Rudalics + + * windows.texi (Displaying Buffers): Describe special handling + of `not-this-window' and `not-this-frame' specifiers for + `display-buffer'. + 2010-10-30 Martin Rudalics * windows.texi (Buffers and Windows, Displaying Buffers): Adapt diff --git a/doc/lispref/windows.texi b/doc/lispref/windows.texi index 448d4898fb3..95bcf4571b2 100644 --- a/doc/lispref/windows.texi +++ b/doc/lispref/windows.texi @@ -1751,6 +1751,13 @@ the values provided by the variables @code{display-buffer-names} and @code{display-buffer-regexps} described below. If their values are nil too, default specifiers are used. + The @code{not-this-window} specifier described below allows as +@sc{cdr} also to specify an arbitrary window. This means that the +window specified here shall not be used for displaying the buffer. The +@code{not-this-frame} specifier described below allows as @sc{cdr} to +also specify an arbitrary frame. This means that the frame specified +here shall not be used for displaying the buffer. + The optional third argument @var{ignore} is ignored. @end deffn diff --git a/lisp/ChangeLog b/lisp/ChangeLog index c95f015c127..fb1e1b0a24d 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,21 @@ +2010-11-02 Martin Rudalics + + * window.el (display-buffer-names): Describe `not-this-window' and + `not-this-frame' specifiers in doc-string. + (display-buffer-in-lru-buffer-window) + (display-buffer-in-lru-window, display-buffer-in-new-window): + Handle `not-this-window' and `not-this-frame' specifiers when + their cdr specifies a window or a frame. + (display-buffer): Explain in doc-string that the cdr of the + `not-this-window' and `not-this-frame' specifiers argument can + name a window. + + * progmodes/compile.el (compilation-start): When displaying outbuf + directly pass height parameters. + (compilation-goto-locus): Use specifiers in display-buffer and + pop-to-buffer calls. Simplify. + (compilation-find-file): Use specifiers in display-buffer calls. + 2010-10-30 Glenn Morris * cus-start.el: Add :set properties for minor modes menu-bar-mode, diff --git a/lisp/progmodes/compile.el b/lisp/progmodes/compile.el index dd30212085e..5a82c6b3b6a 100644 --- a/lisp/progmodes/compile.el +++ b/lisp/progmodes/compile.el @@ -1296,9 +1296,6 @@ Returns the compilation buffer created." command "\n") (setq thisdir default-directory)) (set-buffer-modified-p nil)) - ;; Pop up the compilation buffer. - ;; http://lists.gnu.org/archive/html/emacs-devel/2007-11/msg01638.html - (setq outwin (display-buffer outbuf)) (with-current-buffer outbuf (let ((process-environment (append @@ -1320,8 +1317,18 @@ Returns the compilation buffer created." (list command mode name-function highlight-regexp)) (set (make-local-variable 'revert-buffer-function) 'compilation-revert-buffer) - (set-window-start outwin (point-min)) + ;; The setup function is called before compilation-set-window-height + ;; so it can set the compilation-window-height buffer locally. + (when compilation-process-setup-function + (funcall compilation-process-setup-function)) + (let ((height (buffer-local-value 'compilation-window-height outbuf))) + ;; Pop up the compilation buffer. + (setq outwin + (display-buffer + outbuf + `(same-frame (min-height . ,height) (max-height . ,height))))) + (set-window-start outwin (point-min)) ;; Position point as the user will see it. (let ((desired-visible-point ;; Put it at the end if `compilation-scroll-output' is set. @@ -1333,11 +1340,6 @@ Returns the compilation buffer created." (goto-char desired-visible-point) (set-window-point outwin desired-visible-point))) - ;; The setup function is called before compilation-set-window-height - ;; so it can set the compilation-window-height buffer locally. - (if compilation-process-setup-function - (funcall compilation-process-setup-function)) - (compilation-set-window-height outwin) ;; Start the compilation. (if (fboundp 'start-process) (let ((proc @@ -2094,37 +2096,27 @@ displays at the top of the window; there is no arrow." All arguments are markers. If END-MK is non-nil, mark is set there and overlay is highlighted between MK and END-MK." ;; Show compilation buffer in other window, scrolled to this error. - (let* ((from-compilation-buffer (eq (window-buffer (selected-window)) - (marker-buffer msg))) - ;; Use an existing window if it is in a visible frame. - (pre-existing (get-buffer-window (marker-buffer msg) 0)) - (w (if (and from-compilation-buffer pre-existing) - ;; Calling display-buffer here may end up (partly) hiding - ;; the error location if the two buffers are in two - ;; different frames. So don't do it if it's not necessary. - pre-existing - (let ((display-buffer-reuse-frames t) - (pop-up-windows t)) - ;; Pop up a window. - (display-buffer (marker-buffer msg))))) - (highlight-regexp (with-current-buffer (marker-buffer msg) + (let* ((msg-buffer (marker-buffer msg)) + (mk-buffer (marker-buffer mk)) + (msg-buffer-window + ;; Pop up a window, if possible reusing a window on a + ;; visible or iconified frame. + (let ((height (buffer-local-value + 'compilation-window-height msg-buffer))) + (display-buffer + msg-buffer + `(same-frame (reuse-buffer-window . 0) + (min-height . ,height) (max-height . ,height))))) + (mk-buffer-window + (pop-to-buffer + mk-buffer + ;; Do not use msg-buffer-window. + `(same-frame (not-this-window . ,msg-buffer-window) + (reuse-buffer-window . 0)))) + (highlight-regexp (with-current-buffer msg-buffer ;; also do this while we change buffer - (compilation-set-window w msg) + (compilation-set-window msg-buffer-window msg) compilation-highlight-regexp))) - ;; Ideally, the window-size should be passed to `display-buffer' (via - ;; something like special-display-buffer) so it's only used when - ;; creating a new window. - (unless pre-existing (compilation-set-window-height w)) - - (if from-compilation-buffer - ;; If the compilation buffer window was selected, - ;; keep the compilation buffer in this window; - ;; display the source in another window. - (let ((pop-up-windows t)) - (pop-to-buffer (marker-buffer mk) 'other-window)) - (if (window-dedicated-p (selected-window)) - (pop-to-buffer (marker-buffer mk)) - (switch-to-buffer (marker-buffer mk)))) (unless (eq (goto-char mk) (point)) ;; If narrowing gets in the way of going to the right place, widen. (widen) @@ -2148,7 +2140,7 @@ and overlay is highlighted between MK and END-MK." (setq compilation-highlight-overlay (make-overlay (point-min) (point-min))) (overlay-put compilation-highlight-overlay 'face 'next-error)) - (with-current-buffer (marker-buffer mk) + (with-current-buffer mk-buffer (save-excursion (if end-mk (goto-char end-mk) (end-of-line)) (let ((end (point))) @@ -2224,45 +2216,47 @@ attempts to find a file whose name is produced by (format FMT FILENAME)." (find-file-noselect name)) fmts (cdr fmts))) (setq dirs (cdr dirs))) - (while (null buffer) ;Repeat until the user selects an existing file. + (while (null buffer) ;Repeat until the user selects an existing file. ;; The file doesn't exist. Ask the user where to find it. - (save-excursion ;This save-excursion is probably not right. - (let ((pop-up-windows t)) - (compilation-set-window (display-buffer (marker-buffer marker)) - marker) - (let* ((name (read-file-name - (format "Find this %s in (default %s): " - compilation-error filename) - spec-dir filename t nil - ;; The predicate below is fine when called from - ;; minibuffer-complete-and-exit, but it's too - ;; restrictive otherwise, since it also prevents the - ;; user from completing "fo" to "foo/" when she - ;; wants to enter "foo/bar". - ;; - ;; Try to make sure the user can only select - ;; a valid answer. This predicate may be ignored, - ;; tho, so we still have to double-check afterwards. - ;; TODO: We should probably fix read-file-name so - ;; that it never ignores this predicate, even when - ;; using popup dialog boxes. - ;; (lambda (name) - ;; (if (file-directory-p name) - ;; (setq name (expand-file-name filename name))) - ;; (file-exists-p name)) - )) - (origname name)) - (cond - ((not (file-exists-p name)) - (message "Cannot find file `%s'" name) - (ding) (sit-for 2)) - ((and (file-directory-p name) - (not (file-exists-p - (setq name (expand-file-name filename name))))) - (message "No `%s' in directory %s" filename origname) - (ding) (sit-for 2)) - (t - (setq buffer (find-file-noselect name)))))))) + (save-excursion ;This save-excursion is probably not right. + (compilation-set-window + ;; Apparently the window should be made on the same frame. If + ;; it should be made in another window but the selected one + ;; replace same-frame by t. + (display-buffer (marker-buffer marker) 'same-frame) marker) + (let* ((name (read-file-name + (format "Find this %s in (default %s): " + compilation-error filename) + spec-dir filename t nil + ;; The predicate below is fine when called from + ;; minibuffer-complete-and-exit, but it's too + ;; restrictive otherwise, since it also prevents the + ;; user from completing "fo" to "foo/" when she + ;; wants to enter "foo/bar". + ;; + ;; Try to make sure the user can only select + ;; a valid answer. This predicate may be ignored, + ;; tho, so we still have to double-check afterwards. + ;; TODO: We should probably fix read-file-name so + ;; that it never ignores this predicate, even when + ;; using popup dialog boxes. + ;; (lambda (name) + ;; (if (file-directory-p name) + ;; (setq name (expand-file-name filename name))) + ;; (file-exists-p name)) + )) + (origname name)) + (cond + ((not (file-exists-p name)) + (message "Cannot find file `%s'" name) + (ding) (sit-for 2)) + ((and (file-directory-p name) + (not (file-exists-p + (setq name (expand-file-name filename name))))) + (message "No `%s' in directory %s" filename origname) + (ding) (sit-for 2)) + (t + (setq buffer (find-file-noselect name))))))) ;; Make intangible overlays tangible. ;; This is weird: it's not even clear which is the current buffer, ;; so the code below can't be expected to DTRT here. -- Stef diff --git a/lisp/window.el b/lisp/window.el index 71e77b28f76..e6d2cd74968 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -3638,9 +3638,10 @@ also true lists) whose components are listed below. The specifiers listed below are useful if the location specifier equals either `same-frame' or `other-frame': -- `other-window' with a non-nil cdr can be used to specify that - the selected window must not be used for displaying the buffer - regardless of whether it shows that buffer or any other buffer. +- `not-this-window' with a non-nil cdr can be used to specify + that the selected window must not be used for displaying the + buffer regardless of whether it shows that buffer or any other + buffer. - `reuse-buffer-window' is used to specify whether a window currently showing the buffer may be reused and where to look @@ -3747,6 +3748,9 @@ specifier equals 'same-frame: The specifiers listed next are useful if the location specifier equals 'other-frame: +- `not-this-frame' with a non-nil cdr means that the selected + frame shall not be used for displaying the buffer. + - `graphic-only' with a non-nil cdr means that a new frame shall be made on graphic displays only. @@ -4609,12 +4613,23 @@ description." ;; the first window on the selected frame showing BUFFER (provided ;; there is such a window). (let ((windows (get-buffer-window-list buffer 'nomini frames)) + (not-this-window + (let ((spec-cdr (cdr (assq 'not-this-window specifiers)))) + (cond + ((eq spec-cdr t) + (selected-window)) + (spec-cdr)))) + (not-this-frame + (let ((spec-cdr (cdr (assq 'not-this-frame specifiers)))) + (cond + ((eq spec-cdr t) + (selected-frame)) + (spec-cdr)))) best-window best-time time) (dolist (window windows) - (unless (or (and (eq window (selected-window)) - (assq 'not-this-window specifiers)) - (and (eq (window-frame window) (selected-frame)) - (assq 'not-this-frame specifiers)) + ;; Take care of `not-this-window' and `not-this-frame' specifiers. + (unless (or (eq window not-this-window) + (eq (window-frame window) not-this-frame) (window-minibuffer-p window)) (setq time (window-use-time window)) (when (or (not best-window) (< time best-time)) @@ -4640,13 +4655,25 @@ description." (let ((windows (window-list-1 (frame-first-window (display-buffer-frame)) 'nomini frames)) + (not-this-window + (let ((spec-cdr (cdr (assq 'not-this-window specifiers)))) + (cond + ((eq spec-cdr t) + (selected-window)) + (spec-cdr)))) + (not-this-frame + (let ((spec-cdr (cdr (assq 'not-this-frame specifiers)))) + (cond + ((eq spec-cdr t) + (selected-frame)) + (spec-cdr)))) ;; lru-windows is a list of (window . use-time) pairs. lru-windows) (dolist (window windows) - (unless (or (and (eq window (selected-window)) - (assq 'not-this-window specifiers)) - (and (eq (window-frame window) (selected-frame)) - (assq 'not-this-frame specifiers)) + ;; Take care of `not-this-window' and `not-this-frame' + ;; specifiers. + (unless (or (eq window not-this-window) + (eq (window-frame window) not-this-frame) (window-minibuffer-p window) (window-dedicated-p window)) (setq lru-windows (cons (cons window (window-use-time window)) @@ -4802,9 +4829,14 @@ documentation of `display-buffer-names' for a description." (let* ((frame (display-buffer-frame)) (selected-window (frame-selected-window frame)) window window-specifier side-specifier) - ;; Don't split an unsplittable frame unless SPECIFIERS allow it. - (unless (and (cdr (assq 'unsplittable (frame-parameters frame))) - (not (cdr (assq 'split-unsplittable-frame specifiers)))) + (unless (or (and (cdr (assq 'unsplittable (frame-parameters frame))) + ;; Don't split an unsplittable frame unless + ;; SPECIFIERS allow it. + (not (cdr (assq 'split-unsplittable-frame specifiers)))) + (let ((spec-cdr (cdr (assq 'not-this-frame specifiers)))) + ;; Don't split a window on the selected frame if + ;; `not-this-frame' disallows it. + (or (eq spec-cdr t) (eq spec-cdr (selected-frame))))) (catch 'done (dolist (specifier specifiers) (when (and (consp specifier) (eq (car specifier) 'new-window)) @@ -4901,6 +4933,12 @@ provided by `display-buffer-names' and `display-buffer-regexps'. If these values are nil too, all specifiers are provided by the constant `display-buffer-default-specifiers'. +In addition, the `not-this-window' specifier allows as cdr to +specify an arbitrary window in order to not use that window for +displaying the buffer. The `not-this-frame' specifier allows as +cdr to also specify an arbitrary frame in order to not use that +frame for displaying the buffer. + The optional third argument IGNORE is ignored. The method to display a buffer is derived by combining the values -- 2.39.5