* lisp/follow.el (follow-adjust-window): Remove `dest' argument.
Assume we're already in the proper buffer. Inspired by Anders Lindgren <andlind@gmail.com>. (follow-post-command-hook): Call it from the right buffer. (follow-comint-scroll-to-bottom): Adjust call. (follow-all-followers): Use get-buffer-window-list. Fixes: debbugs:16426
This commit is contained in:
parent
93acfb0eff
commit
87b2a7f2da
2 changed files with 158 additions and 152 deletions
|
@ -1,3 +1,12 @@
|
|||
2014-01-16 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* follow.el (follow-adjust-window): Remove `dest' argument (bug#16426).
|
||||
Assume we're already in the proper buffer.
|
||||
Inspired by Anders Lindgren <andlind@gmail.com>.
|
||||
(follow-post-command-hook): Call it from the right buffer.
|
||||
(follow-comint-scroll-to-bottom): Adjust call.
|
||||
(follow-all-followers): Use get-buffer-window-list.
|
||||
|
||||
2014-01-15 Daniel Colascione <dancol@dancol.org>
|
||||
|
||||
* emacs-lisp/bytecomp.el (byte-compile-file): Use whole
|
||||
|
|
301
lisp/follow.el
301
lisp/follow.el
|
@ -35,7 +35,7 @@
|
|||
;; This means that whenever one window is moved, all the
|
||||
;; others will follow. (Hence the name Follow mode.)
|
||||
;;
|
||||
;; * Should the point (cursor) end up outside a window, another
|
||||
;; * Should point (cursor) end up outside a window, another
|
||||
;; window displaying that point is selected, if possible. This
|
||||
;; makes it possible to walk between windows using normal cursor
|
||||
;; movement commands.
|
||||
|
@ -144,7 +144,7 @@
|
|||
;; this command be added to the global keymap.
|
||||
;;
|
||||
;; follow-recenter C-c . C-l
|
||||
;; Place the point in the center of the middle window,
|
||||
;; Place point in the center of the middle window,
|
||||
;; or a specified number of lines from either top or bottom.
|
||||
;;
|
||||
;; follow-switch-to-buffer C-c . b
|
||||
|
@ -202,6 +202,7 @@
|
|||
;;; Code:
|
||||
|
||||
(require 'easymenu)
|
||||
(eval-when-compile (require 'cl-lib))
|
||||
|
||||
;;; Variables
|
||||
|
||||
|
@ -390,7 +391,7 @@ virtual window. This is accomplished by two main techniques:
|
|||
This means that whenever one window is moved, all the
|
||||
others will follow. (Hence the name Follow mode.)
|
||||
|
||||
* Should the point (cursor) end up outside a window, another
|
||||
* Should point (cursor) end up outside a window, another
|
||||
window displaying that point is selected, if possible. This
|
||||
makes it possible to walk between windows using normal cursor
|
||||
movement commands.
|
||||
|
@ -532,7 +533,7 @@ This is to be called by `comint-postoutput-scroll-to-bottom'."
|
|||
(select-window win)
|
||||
(goto-char pos)
|
||||
(setq follow-windows-start-end-cache nil)
|
||||
(follow-adjust-window win pos)
|
||||
(follow-adjust-window win)
|
||||
(unless is-selected
|
||||
(select-window selected)
|
||||
(set-buffer buffer))))))
|
||||
|
@ -744,12 +745,9 @@ contains only windows in the same frame as WIN. If WIN is nil,
|
|||
it defaults to the selected window."
|
||||
(unless (window-live-p win)
|
||||
(setq win (selected-window)))
|
||||
(let ((buffer (window-buffer win))
|
||||
windows)
|
||||
(dolist (w (window-list (window-frame win) 'no-minibuf win))
|
||||
(if (eq (window-buffer w) buffer)
|
||||
(push w windows)))
|
||||
(sort windows 'follow--window-sorter)))
|
||||
(let ((windows (get-buffer-window-list
|
||||
(window-buffer win) 'no-minibuf (window-frame win))))
|
||||
(sort windows #'follow--window-sorter)))
|
||||
|
||||
(defun follow-split-followers (windows &optional win)
|
||||
"Split WINDOWS into two sets: predecessors and successors.
|
||||
|
@ -847,7 +845,7 @@ returned by `follow-windows-start-end'."
|
|||
(setq win-start-end (cdr win-start-end)))
|
||||
result))
|
||||
|
||||
;; Check if the point is visible in all windows. (So that
|
||||
;; Check if point is visible in all windows. (So that
|
||||
;; no one will be recentered.)
|
||||
|
||||
(defun follow-point-visible-all-windows-p (win-start-end)
|
||||
|
@ -866,7 +864,7 @@ returned by `follow-windows-start-end'."
|
|||
;; will lead to a redisplay of the screen later on.
|
||||
;;
|
||||
;; This is used with the first window in a follow chain. The reason
|
||||
;; is that we want to detect that the point is outside the window.
|
||||
;; is that we want to detect that point is outside the window.
|
||||
;; (Without the update, the start of the window will move as the
|
||||
;; user presses BackSpace, and the other window redisplay routines
|
||||
;; will move the start of the window in the wrong direction.)
|
||||
|
@ -898,7 +896,7 @@ Return the selected window."
|
|||
|
||||
;; Lets select a window showing the end. Make sure we only select it if
|
||||
;; it wasn't just moved here. (I.e. M-> shall not unconditionally place
|
||||
;; the point in the selected window.)
|
||||
;; point in the selected window.)
|
||||
;;
|
||||
;; (Compatibility kludge: in Emacs `window-end' is equal to `point-max';
|
||||
;; in XEmacs, it is equal to `point-max + 1'. Should I really bother
|
||||
|
@ -924,10 +922,10 @@ Return the selected window."
|
|||
win))
|
||||
|
||||
|
||||
;; Select a window that will display the point if the windows would
|
||||
;; Select a window that will display point if the windows would
|
||||
;; be redisplayed with the first window fixed. This is useful for
|
||||
;; example when the user has pressed return at the bottom of a window
|
||||
;; as the point is not visible in any window.
|
||||
;; as point is not visible in any window.
|
||||
|
||||
(defun follow-select-if-visible-from-first (dest windows)
|
||||
"Try to select one of WINDOWS without repositioning the topmost window.
|
||||
|
@ -969,7 +967,7 @@ Otherwise, return nil."
|
|||
|
||||
(defun follow-redisplay (&optional windows win preserve-win)
|
||||
"Reposition the WINDOWS around WIN.
|
||||
Should the point be too close to the roof we redisplay everything
|
||||
Should point be too close to the roof we redisplay everything
|
||||
from the top. WINDOWS should contain a list of windows to
|
||||
redisplay; it is assumed that WIN is a member of the list.
|
||||
Should WINDOWS be nil, the windows displaying the
|
||||
|
@ -1124,158 +1122,157 @@ non-first windows in Follow mode."
|
|||
(with-current-buffer (window-buffer win)
|
||||
(unless (and (symbolp this-command)
|
||||
(get this-command 'follow-mode-use-cache))
|
||||
(setq follow-windows-start-end-cache nil)))
|
||||
(follow-adjust-window win (point)))))
|
||||
|
||||
(defun follow-adjust-window (win dest)
|
||||
;; Adjust the window WIN and its followers.
|
||||
(with-current-buffer (window-buffer win)
|
||||
(when (and follow-mode
|
||||
(not (window-minibuffer-p win)))
|
||||
(let* ((windows (follow-all-followers win))
|
||||
(win-start-end (progn
|
||||
(follow-update-window-start (car windows))
|
||||
(follow-windows-start-end windows)))
|
||||
(aligned (follow-windows-aligned-p win-start-end))
|
||||
(visible (follow-pos-visible dest win win-start-end))
|
||||
selected-window-up-to-date)
|
||||
(unless (and aligned visible)
|
||||
(setq follow-windows-start-end-cache nil))
|
||||
(follow-adjust-window win)))))
|
||||
|
||||
;; Select a window to display point.
|
||||
(unless follow-internal-force-redisplay
|
||||
(if (eq dest (point-max))
|
||||
;; Be careful at point-max: the display can be aligned
|
||||
;; while DEST can be visible in several windows.
|
||||
(cond
|
||||
;; Select the current window, but only when the display
|
||||
;; is correct. (When inserting characters in a tail
|
||||
;; window, the display is not correct, as they are
|
||||
;; shown twice.)
|
||||
;;
|
||||
;; Never stick to the current window after a deletion.
|
||||
;; Otherwise, when typing `DEL' in a window showing
|
||||
;; only the end of the file, a character would be
|
||||
;; removed from the window above, which is very
|
||||
;; unintuitive.
|
||||
((and visible
|
||||
aligned
|
||||
(not (memq this-command
|
||||
'(backward-delete-char
|
||||
delete-backward-char
|
||||
backward-delete-char-untabify
|
||||
kill-region))))
|
||||
(follow-debug-message "Max: same"))
|
||||
;; If the end is visible, and the window doesn't
|
||||
;; seems like it just has been moved, select it.
|
||||
((follow-select-if-end-visible win-start-end)
|
||||
(follow-debug-message "Max: end visible")
|
||||
(setq visible t aligned nil)
|
||||
(goto-char dest))
|
||||
;; Just show the end...
|
||||
(t
|
||||
(follow-debug-message "Max: default")
|
||||
(select-window (car (last windows)))
|
||||
(goto-char dest)
|
||||
(setq visible nil aligned nil)))
|
||||
(defun follow-adjust-window (win)
|
||||
;; Adjust the window WIN and its followers.
|
||||
(cl-assert (eq (window-buffer win) (current-buffer)))
|
||||
(when (and follow-mode
|
||||
(not (window-minibuffer-p win)))
|
||||
(let* ((dest (point))
|
||||
(windows (follow-all-followers win))
|
||||
(win-start-end (progn
|
||||
(follow-update-window-start (car windows))
|
||||
(follow-windows-start-end windows)))
|
||||
(aligned (follow-windows-aligned-p win-start-end))
|
||||
(visible (follow-pos-visible dest win win-start-end))
|
||||
selected-window-up-to-date)
|
||||
(unless (and aligned visible)
|
||||
(setq follow-windows-start-end-cache nil))
|
||||
|
||||
;; We're not at the end, here life is much simpler.
|
||||
(cond
|
||||
;; This is the normal case!
|
||||
;; It should be optimized for speed.
|
||||
((and visible aligned)
|
||||
(follow-debug-message "same"))
|
||||
;; Pick a position in any window. If the display is ok,
|
||||
;; this picks the `correct' window.
|
||||
((follow-select-if-visible dest win-start-end)
|
||||
(follow-debug-message "visible")
|
||||
(goto-char dest)
|
||||
;; Perform redisplay, in case line is partially visible.
|
||||
(setq visible nil))
|
||||
;; Not visible anywhere else, lets pick this one.
|
||||
(visible
|
||||
(follow-debug-message "visible in selected."))
|
||||
;; If DEST is before the first window start, select the
|
||||
;; first window.
|
||||
((< dest (nth 1 (car win-start-end)))
|
||||
(follow-debug-message "before first")
|
||||
(select-window (car windows))
|
||||
(goto-char dest)
|
||||
(setq visible nil aligned nil))
|
||||
;; If we can position the cursor without moving the first
|
||||
;; window, do it. This is the case that catches `RET' at
|
||||
;; the bottom of a window.
|
||||
((follow-select-if-visible-from-first dest windows)
|
||||
(follow-debug-message "Below first")
|
||||
(setq visible t aligned t))
|
||||
;; None of the above. Stick to the selected window.
|
||||
(t
|
||||
(follow-debug-message "None")
|
||||
(setq visible nil aligned nil))))
|
||||
;; Select a window to display point.
|
||||
(unless follow-internal-force-redisplay
|
||||
(if (eq dest (point-max))
|
||||
;; Be careful at point-max: the display can be aligned
|
||||
;; while DEST can be visible in several windows.
|
||||
(cond
|
||||
;; Select the current window, but only when the display
|
||||
;; is correct. (When inserting characters in a tail
|
||||
;; window, the display is not correct, as they are
|
||||
;; shown twice.)
|
||||
;;
|
||||
;; Never stick to the current window after a deletion.
|
||||
;; Otherwise, when typing `DEL' in a window showing
|
||||
;; only the end of the file, a character would be
|
||||
;; removed from the window above, which is very
|
||||
;; unintuitive.
|
||||
((and visible
|
||||
aligned
|
||||
(not (memq this-command
|
||||
'(backward-delete-char
|
||||
delete-backward-char
|
||||
backward-delete-char-untabify
|
||||
kill-region))))
|
||||
(follow-debug-message "Max: same"))
|
||||
;; If the end is visible, and the window doesn't
|
||||
;; seems like it just has been moved, select it.
|
||||
((follow-select-if-end-visible win-start-end)
|
||||
(follow-debug-message "Max: end visible")
|
||||
(setq visible t aligned nil)
|
||||
(goto-char dest))
|
||||
;; Just show the end...
|
||||
(t
|
||||
(follow-debug-message "Max: default")
|
||||
(select-window (car (last windows)))
|
||||
(goto-char dest)
|
||||
(setq visible nil aligned nil)))
|
||||
|
||||
;; If a new window was selected, make sure that the old is
|
||||
;; not scrolled when the point is outside the window.
|
||||
(unless (eq win (selected-window))
|
||||
(let ((p (window-point win)))
|
||||
(set-window-start win (window-start win) nil)
|
||||
(set-window-point win p))))
|
||||
;; We're not at the end, here life is much simpler.
|
||||
(cond
|
||||
;; This is the normal case!
|
||||
;; It should be optimized for speed.
|
||||
((and visible aligned)
|
||||
(follow-debug-message "same"))
|
||||
;; Pick a position in any window. If the display is ok,
|
||||
;; this picks the `correct' window.
|
||||
((follow-select-if-visible dest win-start-end)
|
||||
(follow-debug-message "visible")
|
||||
(goto-char dest)
|
||||
;; Perform redisplay, in case line is partially visible.
|
||||
(setq visible nil))
|
||||
;; Not visible anywhere else, lets pick this one.
|
||||
(visible
|
||||
(follow-debug-message "visible in selected."))
|
||||
;; If DEST is before the first window start, select the
|
||||
;; first window.
|
||||
((< dest (nth 1 (car win-start-end)))
|
||||
(follow-debug-message "before first")
|
||||
(select-window (car windows))
|
||||
(goto-char dest)
|
||||
(setq visible nil aligned nil))
|
||||
;; If we can position the cursor without moving the first
|
||||
;; window, do it. This is the case that catches `RET' at
|
||||
;; the bottom of a window.
|
||||
((follow-select-if-visible-from-first dest windows)
|
||||
(follow-debug-message "Below first")
|
||||
(setq visible t aligned t))
|
||||
;; None of the above. Stick to the selected window.
|
||||
(t
|
||||
(follow-debug-message "None")
|
||||
(setq visible nil aligned nil))))
|
||||
|
||||
(unless visible
|
||||
;; If point may not be visible in the selected window,
|
||||
;; perform a redisplay; this ensures scrolling.
|
||||
(let ((opoint (point)))
|
||||
(redisplay)
|
||||
;; If this `redisplay' moved point, we got clobbered by a
|
||||
;; previous call to `set-window-start'. Try again.
|
||||
(when (/= (point) opoint)
|
||||
(goto-char opoint)
|
||||
(redisplay)))
|
||||
;; If a new window was selected, make sure that the old is
|
||||
;; not scrolled when point is outside the window.
|
||||
(unless (eq win (selected-window))
|
||||
(let ((p (window-point win)))
|
||||
(set-window-start win (window-start win) nil)
|
||||
(set-window-point win p))))
|
||||
|
||||
(setq selected-window-up-to-date t)
|
||||
(follow-avoid-tail-recenter)
|
||||
(setq win-start-end (follow-windows-start-end windows)
|
||||
follow-windows-start-end-cache nil
|
||||
aligned nil))
|
||||
(unless visible
|
||||
;; If point may not be visible in the selected window,
|
||||
;; perform a redisplay; this ensures scrolling.
|
||||
(let ((opoint (point)))
|
||||
(redisplay)
|
||||
;; If this `redisplay' moved point, we got clobbered by a
|
||||
;; previous call to `set-window-start'. Try again.
|
||||
(when (/= (point) opoint)
|
||||
(goto-char opoint)
|
||||
(redisplay)))
|
||||
|
||||
;; Now redraw the windows around the selected window.
|
||||
(unless (and (not follow-internal-force-redisplay)
|
||||
(or aligned
|
||||
(follow-windows-aligned-p win-start-end))
|
||||
(follow-point-visible-all-windows-p win-start-end))
|
||||
(setq follow-internal-force-redisplay nil)
|
||||
(follow-redisplay windows (selected-window)
|
||||
selected-window-up-to-date)
|
||||
(setq win-start-end (follow-windows-start-end windows)
|
||||
follow-windows-start-end-cache nil)
|
||||
;; The point can ends up in another window when DEST is at
|
||||
;; the beginning of the buffer and the selected window is
|
||||
;; not the first. It can also happen when long lines are
|
||||
;; used and there is a big difference between the width of
|
||||
;; the windows. (When scrolling one line in a wide window
|
||||
;; which will cause a move larger that an entire small
|
||||
;; window.)
|
||||
(unless (follow-pos-visible dest win win-start-end)
|
||||
(follow-select-if-visible dest win-start-end)
|
||||
(goto-char dest)))
|
||||
(setq selected-window-up-to-date t)
|
||||
(follow-avoid-tail-recenter)
|
||||
(setq win-start-end (follow-windows-start-end windows)
|
||||
follow-windows-start-end-cache nil
|
||||
aligned nil))
|
||||
|
||||
;; If the region is visible, make it look good when spanning
|
||||
;; multiple windows.
|
||||
;; Now redraw the windows around the selected window.
|
||||
(unless (and (not follow-internal-force-redisplay)
|
||||
(or aligned
|
||||
(follow-windows-aligned-p win-start-end))
|
||||
(follow-point-visible-all-windows-p win-start-end))
|
||||
(setq follow-internal-force-redisplay nil)
|
||||
(follow-redisplay windows (selected-window)
|
||||
selected-window-up-to-date)
|
||||
(setq win-start-end (follow-windows-start-end windows)
|
||||
follow-windows-start-end-cache nil)
|
||||
;; Point can end up in another window when DEST is at
|
||||
;; the beginning of the buffer and the selected window is
|
||||
;; not the first. It can also happen when long lines are
|
||||
;; used and there is a big difference between the width of
|
||||
;; the windows. (When scrolling one line in a wide window
|
||||
;; which will cause a move larger that an entire small
|
||||
;; window.)
|
||||
(unless (follow-pos-visible dest win win-start-end)
|
||||
(follow-select-if-visible dest win-start-end)
|
||||
(goto-char dest)))
|
||||
|
||||
;; FIXME: Why not use `use-region-p' here?
|
||||
(when (region-active-p)
|
||||
(follow-maximize-region
|
||||
(selected-window) windows win-start-end)))
|
||||
;; If the region is visible, make it look good when spanning
|
||||
;; multiple windows.
|
||||
(when (region-active-p)
|
||||
(follow-maximize-region
|
||||
(selected-window) windows win-start-end)))
|
||||
|
||||
;; Whether or not the buffer was in follow mode, update windows
|
||||
;; displaying the tail so that Emacs won't recenter them.
|
||||
(follow-avoid-tail-recenter))))
|
||||
;; Whether or not the buffer was in follow mode, update windows
|
||||
;; displaying the tail so that Emacs won't recenter them.
|
||||
(follow-avoid-tail-recenter)))
|
||||
|
||||
;;; The region
|
||||
|
||||
;; Tries to make the highlighted area representing the region look
|
||||
;; good when spanning several windows.
|
||||
;;
|
||||
;; Not perfect, as the point can't be placed at window end, only at
|
||||
;; Not perfect, as point can't be placed at window end, only at
|
||||
;; end-1. This will highlight a little bit in windows above
|
||||
;; the current.
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue