+2015-03-23 Daniel Colascione <dancol@dancol.org>
+
+ 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 <jackson@jacksonrayhamilton.com>
* textmodes/sgml-mode.el (sgml-attribute-offset): New defcustom.
(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)
(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
(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))))
(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
(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.
(window-buffer window))))
(if (integerp t-p-w-w)
(< (window-width window) t-p-w-w)
- t-p-w-w))))
+ t-p-w-w))))
+
+\f
+;; 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)
+
\f
;; Some of these are in tutorial--default-keys, so update that if you
;; change these.