From: Daniel Colascione Date: Mon, 23 Mar 2015 04:09:21 +0000 (-0700) Subject: Automatically adjust process window sizes X-Git-Tag: emacs-25.0.90~2564^2~103 X-Git-Url: https://code.delx.au/gnu-emacs/commitdiff_plain/165bea78008ec7545698f2e893821b4090f20c79 Automatically adjust process window sizes * lisp/window.el (window-adjust-process-window-size-function): New customizable variable. (window-adjust-process-window-size) (window-adjust-process-window-size-smallest) (window-adjust-process-window-size-largest) (window--process-window-list, window--adjust-process-windows): New functions. (window-configuration-change-hook): Add `window--adjust-process-windows'. * lisp/term.el (term-mode): Observe result of `window-adjust-process-window-size-function'. (term-check-size): Delete. --- diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 1b8a4d3ce1..596b6e2ccb 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,20 @@ +2015-03-23 Daniel Colascione + + Automatically adjust process window sizes. + + * window.el (window-adjust-process-window-size-function): New + customizable variable. + (window-adjust-process-window-size) + (window-adjust-process-window-size-smallest) + (window-adjust-process-window-size-largest) + (window--process-window-list, window--adjust-process-windows): + New functions. + (window-configuration-change-hook): Add + `window--adjust-process-windows'. + * term.el (term-mode): Observe result of + `window-adjust-process-window-size-function'. + (term-check-size): Delete. + 2015-03-22 Jackson Ray Hamilton * textmodes/sgml-mode.el (sgml-attribute-offset): New defcustom. diff --git a/lisp/term.el b/lisp/term.el index a629af90d3..43138fa6dd 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -1145,7 +1145,7 @@ Entry to this mode runs the hooks on `term-mode-hook'." (make-local-variable 'term-scroll-show-maximum-output) (make-local-variable 'term-ptyp) (make-local-variable 'term-exec-hook) - (make-local-variable 'term-vertical-motion) + (set (make-local-variable 'term-vertical-motion) 'vertical-motion) (set (make-local-variable 'term-pending-delete-marker) (make-marker)) (make-local-variable 'term-current-face) (term-ansi-reset) @@ -1155,6 +1155,13 @@ Entry to this mode runs the hooks on `term-mode-hook'." (set (make-local-variable 'font-lock-defaults) '(nil t)) + (add-function :filter-return + (local 'window-adjust-process-window-size-function) + (lambda (size) + (when size + (term-reset-size (cdr size) (car size))) + size)) + (easy-menu-add term-terminal-menu) (easy-menu-add term-signals-menu) (or term-input-ring @@ -1197,12 +1204,6 @@ Entry to this mode runs the hooks on `term-mode-hook'." (goto-char save-point))) found)) -(defun term-check-size (process) - (when (or (/= term-height (window-text-height)) - (/= term-width (term-window-width))) - (term-reset-size (window-text-height) (term-window-width)) - (set-process-window-size process term-height term-width))) - (defun term-send-raw-string (chars) (deactivate-mark) (let ((proc (get-buffer-process (current-buffer)))) @@ -2772,15 +2773,11 @@ See `term-prompt-regexp'." (when (/= (point) (process-mark proc)) (setq save-point (point-marker))) - ;; Note if the window size has changed. We used to reset - ;; point too, but that gives incorrect results (Bug#4635). - (if (eq (window-buffer) (current-buffer)) - (progn - (setq term-vertical-motion (symbol-function 'vertical-motion)) - (term-check-size proc)) - (setq term-vertical-motion - (symbol-function 'term-buffer-vertical-motion))) - (setq save-marker (copy-marker (process-mark proc))) + (setf term-vertical-motion + (if (eq (window-buffer) (current-buffer)) + 'vertical-motion + 'term-buffer-vertical-motion)) + (setq save-marker (copy-marker (process-mark proc))) (goto-char (process-mark proc)) (save-restriction @@ -3082,9 +3079,7 @@ See `term-prompt-regexp'." (eq (window-buffer selected) (current-buffer))) (term-display-line (car term-pending-frame) (cdr term-pending-frame)) - (setq term-pending-frame nil) - ;; We have created a new window, so check the window size. - (term-check-size proc)) + (setq term-pending-frame nil)) ;; Scroll each window displaying the buffer but (by default) ;; only if the point matches the process-mark we started with. diff --git a/lisp/window.el b/lisp/window.el index d17605099a..94fe521b73 100644 --- a/lisp/window.el +++ b/lisp/window.el @@ -8029,7 +8029,107 @@ Otherwise, consult the value of `truncate-partial-width-windows' (window-buffer window)))) (if (integerp t-p-w-w) (< (window-width window) t-p-w-w) - t-p-w-w)))) + t-p-w-w)))) + + +;; Automatically inform subprocesses of changes to window size. + +(defcustom window-adjust-process-window-size-function + 'window-adjust-process-window-size-smallest + "Control how Emacs chooses inferior process window sizes. +Emacs uses this function to tell processes the space they have +available for displaying their output. After each window +configuration change, Emacs calls the value of +`window-adjust-process-window-size-function' for each process +with a buffer being displayed in at least one window. +This function is responsible for combining the sizes of the +displayed windows and returning a cons (WIDTH . HEIGHT) +describing the width and height with which Emacs will call +`set-process-window-size' for that process. If the function +returns `nil', Emacs does not call `set-process-window-size'. + +This function is called with the process buffer as the current +buffer and with two arguments: the process and a list of windows +displaying process. Modes can make this variable buffer-local; +additionally, the `adjust-window-size-function' process property +overrides the global or buffer-local value of +`window-adjust-process-window-size-function'." + :type '(choice + (const :tag "Minimum area of any window" + window-adjust-process-window-size-smallest) + (const :tag "Maximum area of any window" + window-adjust-process-window-size-largest) + (const :tag "Do not adjust process window sizes" ignore) + function) + :group 'windows + :version "25.1") + +(defun window-adjust-process-window-size (reducer process windows) + "Adjust the process window size of PROCESS. +WINDOWS is a list of windows associated with PROCESS. REDUCER is +a two-argument function used to combine the widths and heights of +the given windows." + (when windows + (let ((width (window-body-width (car windows))) + (height (window-body-height (car windows)))) + (dolist (window (cdr windows)) + (setf width (funcall reducer width (window-body-width window))) + (setf height (funcall reducer height (window-body-height window)))) + (cons width height)))) + +(defun window-adjust-process-window-size-smallest (process windows) + "Adjust the process window size of PROCESS. +WINDOWS is a list of windows associated with PROCESS. Choose the +smallest area availabe for displaying PROCESS's output." + (window-adjust-process-window-size #'min process windows)) + +(defun window-adjust-process-window-size-largest (process windows) + "Adjust the process window size of PROCESS. +WINDOWS is a list of windows associated with PROCESS. Choose the +largest area availabe for displaying PROCESS's output." + (window-adjust-process-window-size #'max process windows)) + +(defun window--process-window-list () + "Return an alist mapping processes to associated windows. +A window is associated with a process if that window is +displaying that processes's buffer." + (let ((processes (process-list)) + (process-windows nil)) + (walk-windows + (lambda (window) + (let ((buffer (window-buffer window)) + (iter processes)) + (while (let ((process (car iter))) + (if (and (process-live-p process) + (eq buffer (process-buffer process))) + (let ((procwin (assq process process-windows))) + ;; Add this window to the list of windows + ;; displaying process. + (if procwin + (push window (cdr procwin)) + (push (list process window) process-windows)) + ;; We found our process for this window, so + ;; stop iterating over the process list. + nil) + (setf iter (cdr iter))))))) + 1 t) + process-windows)) + +(defun window--adjust-process-windows () + "Update process window sizes to match the current window configuration." + (dolist (procwin (window--process-window-list)) + (let ((process (car procwin))) + (with-demoted-errors "Error adjusting window size: %S" + (with-current-buffer (process-buffer process) + (let ((size (funcall + (or (process-get process 'adjust-window-size-function) + window-adjust-process-window-size-function) + process (cdr procwin)))) + (when size + (set-process-window-size process (cdr size) (car size))))))))) + +(add-hook 'window-configuration-change-hook 'window--adjust-process-windows) + ;; Some of these are in tutorial--default-keys, so update that if you ;; change these.