* lisp/window.el (with-displayed-buffer-window): New macro.

(with-temp-buffer-window, with-current-buffer-window):
Use `macroexp-let2' to evaluate and bind variables
in the same order as macro arguments.
(display-buffer--action-function-custom-type): Add
`display-buffer-below-selected' and `display-buffer-at-bottom'.

* lisp/minibuffer.el (minibuffer-completion-help): Replace
`with-output-to-temp-buffer' with `with-displayed-buffer-window'
with actions that display *Completions* at-bottom when called
from the minibuffer, or below-selected in a normal buffer.
Associate `window-height' with `fit-window-to-buffer'.
Let-bind `pop-up-windows' to nil.

* lisp/dired.el (dired-mark-pop-up): Use `with-displayed-buffer-window'
instead of `with-current-buffer-window'.

Fixes: debbugs:17809
This commit is contained in:
Juri Linkov 2014-07-08 11:02:50 +03:00
parent f298de5264
commit f0f70ec0bc
4 changed files with 113 additions and 34 deletions

View file

@ -1,3 +1,22 @@
2014-07-08 Juri Linkov <juri@jurta.org>
* window.el (with-displayed-buffer-window): New macro.
(with-temp-buffer-window, with-current-buffer-window):
Use `macroexp-let2' to evaluate and bind variables
in the same order as macro arguments.
(display-buffer--action-function-custom-type): Add
`display-buffer-below-selected' and `display-buffer-at-bottom'.
* minibuffer.el (minibuffer-completion-help): Replace
`with-output-to-temp-buffer' with `with-displayed-buffer-window'
with actions that display *Completions* at-bottom when called
from the minibuffer, or below-selected in a normal buffer.
Associate `window-height' with `fit-window-to-buffer'.
Let-bind `pop-up-windows' to nil.
* dired.el (dired-mark-pop-up): Use `with-displayed-buffer-window'
instead of `with-current-buffer-window'. (Bug#17809)
2014-07-07 Luke Lee <luke.yx.lee@gmail.com>
* progmodes/hideif.el (hide-ifdef-env): Change to global.

View file

@ -3103,20 +3103,20 @@ argument or confirmation)."
;; Mark *Marked Files* window as softly-dedicated, to prevent
;; other buffers e.g. *Completions* from reusing it (bug#17554).
(display-buffer-mark-dedicated 'soft))
(with-current-buffer buffer
(with-current-buffer-window
buffer
(cons 'display-buffer-below-selected
'((window-height . fit-window-to-buffer)))
#'(lambda (window _value)
(with-selected-window window
(unwind-protect
(apply function args)
(when (window-live-p window)
(quit-restore-window window 'kill)))))
;; Handle (t FILE) just like (FILE), here. That value is
;; used (only in some cases), to mean just one file that was
;; marked, rather than the current line file.
(with-displayed-buffer-window
buffer
(cons 'display-buffer-below-selected
'((window-height . fit-window-to-buffer)))
#'(lambda (window _value)
(with-selected-window window
(unwind-protect
(apply function args)
(when (window-live-p window)
(quit-restore-window window 'kill)))))
;; Handle (t FILE) just like (FILE), here. That value is
;; used (only in some cases), to mean just one file that was
;; marked, rather than the current line file.
(with-current-buffer buffer
(dired-format-columns-of-files
(if (eq (car files) t) (cdr files) files))
(remove-text-properties (point-min) (point-max)

View file

@ -1794,8 +1794,29 @@ variables.")
;; window, mark it as softly-dedicated, so bury-buffer in
;; minibuffer-hide-completions will know whether to
;; delete the window or not.
(display-buffer-mark-dedicated 'soft))
(with-output-to-temp-buffer "*Completions*"
(display-buffer-mark-dedicated 'soft)
;; Disable `pop-up-windows' temporarily to allow
;; `display-buffer--maybe-pop-up-frame-or-window'
;; in the display actions below to pop up a frame
;; if `pop-up-frames' is non-nil, but not to pop up a window.
(pop-up-windows nil))
(with-displayed-buffer-window
"*Completions*"
;; This is a copy of `display-buffer-fallback-action'
;; where `display-buffer-use-some-window' is replaced
;; with `display-buffer-at-bottom'.
`((display-buffer--maybe-same-window
display-buffer-reuse-window
display-buffer--maybe-pop-up-frame-or-window
;; Use `display-buffer-below-selected' for inline completions,
;; but not in the minibuffer (e.g. in `eval-expression')
;; for which `display-buffer-at-bottom' is used.
,(if (and completion-in-region-mode-predicate
(not (minibuffer-selected-window)))
'display-buffer-below-selected
'display-buffer-at-bottom))
(window-height . fit-window-to-buffer))
nil
;; Remove the base-size tail because `sort' requires a properly
;; nil-terminated list.
(when last (setcdr last nil))

View file

@ -185,16 +185,19 @@ argument replaces this)."
(let ((buffer (make-symbol "buffer"))
(window (make-symbol "window"))
(value (make-symbol "value")))
`(let* ((,buffer (temp-buffer-window-setup ,buffer-or-name))
(standard-output ,buffer)
,window ,value)
(setq ,value (progn ,@body))
(with-current-buffer ,buffer
(setq ,window (temp-buffer-window-show ,buffer ,action)))
(macroexp-let2 nil vbuffer-or-name buffer-or-name
(macroexp-let2 nil vaction action
(macroexp-let2 nil vquit-function quit-function
`(let* ((,buffer (temp-buffer-window-setup ,vbuffer-or-name))
(standard-output ,buffer)
,window ,value)
(setq ,value (progn ,@body))
(with-current-buffer ,buffer
(setq ,window (temp-buffer-window-show ,buffer ,vaction)))
(if (functionp ,quit-function)
(funcall ,quit-function ,window ,value)
,value))))
(if (functionp ,vquit-function)
(funcall ,vquit-function ,window ,value)
,value)))))))
(defmacro with-current-buffer-window (buffer-or-name action quit-function &rest body)
"Evaluate BODY with a buffer BUFFER-OR-NAME current and show that buffer.
@ -205,16 +208,50 @@ BODY."
(let ((buffer (make-symbol "buffer"))
(window (make-symbol "window"))
(value (make-symbol "value")))
`(let* ((,buffer (temp-buffer-window-setup ,buffer-or-name))
(standard-output ,buffer)
,window ,value)
(with-current-buffer ,buffer
(setq ,value (progn ,@body))
(setq ,window (temp-buffer-window-show ,buffer ,action)))
(macroexp-let2 nil vbuffer-or-name buffer-or-name
(macroexp-let2 nil vaction action
(macroexp-let2 nil vquit-function quit-function
`(let* ((,buffer (temp-buffer-window-setup ,vbuffer-or-name))
(standard-output ,buffer)
,window ,value)
(with-current-buffer ,buffer
(setq ,value (progn ,@body))
(setq ,window (temp-buffer-window-show ,buffer ,vaction)))
(if (functionp ,quit-function)
(funcall ,quit-function ,window ,value)
,value))))
(if (functionp ,vquit-function)
(funcall ,vquit-function ,window ,value)
,value)))))))
(defmacro with-displayed-buffer-window (buffer-or-name action quit-function &rest body)
"Show a buffer BUFFER-OR-NAME and evaluate BODY in that buffer.
This construct is like `with-current-buffer-window' but unlike that
displays the buffer specified by BUFFER-OR-NAME before running BODY."
(declare (debug t))
(let ((buffer (make-symbol "buffer"))
(window (make-symbol "window"))
(value (make-symbol "value")))
(macroexp-let2 nil vbuffer-or-name buffer-or-name
(macroexp-let2 nil vaction action
(macroexp-let2 nil vquit-function quit-function
`(let* ((,buffer (temp-buffer-window-setup ,vbuffer-or-name))
(standard-output ,buffer)
,window ,value)
(with-current-buffer ,buffer
(setq ,window (temp-buffer-window-show ,buffer ,vaction)))
(let ((inhibit-read-only t)
(inhibit-modification-hooks t))
(setq ,value (progn ,@body)))
(set-window-point ,window (point-min))
(when (functionp (cdr (assq 'window-height (cdr ,vaction))))
(ignore-errors
(funcall (cdr (assq 'window-height (cdr ,vaction))) ,window)))
(if (functionp ,vquit-function)
(funcall ,vquit-function ,window ,value)
,value)))))))
;; The following two functions are like `window-next-sibling' and
;; `window-prev-sibling' but the WINDOW argument is _not_ optional (so
@ -5980,6 +6017,8 @@ 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-below-selected)
(const display-buffer-at-bottom)
(const display-buffer-in-previous-window)
(const display-buffer-use-some-window)
(function :tag "Other function"))