aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2014-01-15 19:26:45 -0500
committerStefan Monnier2014-01-15 19:26:45 -0500
commit87b2a7f2da9a94f794f80494d2cf42b8c3e041f1 (patch)
tree069f4c4448bda5f127c777e84064c2a9f9c00b39
parent93acfb0eff2c089abf14caa95f5599cdbd99fb48 (diff)
downloademacs-87b2a7f2da9a94f794f80494d2cf42b8c3e041f1.tar.gz
emacs-87b2a7f2da9a94f794f80494d2cf42b8c3e041f1.zip
* 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
-rw-r--r--lisp/ChangeLog9
-rw-r--r--lisp/follow.el317
2 files changed, 166 insertions, 160 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index fa2f97d0702..56d4a83501a 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,12 @@
12014-01-16 Stefan Monnier <monnier@iro.umontreal.ca>
2
3 * follow.el (follow-adjust-window): Remove `dest' argument (bug#16426).
4 Assume we're already in the proper buffer.
5 Inspired by Anders Lindgren <andlind@gmail.com>.
6 (follow-post-command-hook): Call it from the right buffer.
7 (follow-comint-scroll-to-bottom): Adjust call.
8 (follow-all-followers): Use get-buffer-window-list.
9
12014-01-15 Daniel Colascione <dancol@dancol.org> 102014-01-15 Daniel Colascione <dancol@dancol.org>
2 11
3 * emacs-lisp/bytecomp.el (byte-compile-file): Use whole 12 * emacs-lisp/bytecomp.el (byte-compile-file): Use whole
diff --git a/lisp/follow.el b/lisp/follow.el
index 19ff6f8f0aa..72b4a8aec29 100644
--- a/lisp/follow.el
+++ b/lisp/follow.el
@@ -35,7 +35,7 @@
35;; This means that whenever one window is moved, all the 35;; This means that whenever one window is moved, all the
36;; others will follow. (Hence the name Follow mode.) 36;; others will follow. (Hence the name Follow mode.)
37;; 37;;
38;; * Should the point (cursor) end up outside a window, another 38;; * Should point (cursor) end up outside a window, another
39;; window displaying that point is selected, if possible. This 39;; window displaying that point is selected, if possible. This
40;; makes it possible to walk between windows using normal cursor 40;; makes it possible to walk between windows using normal cursor
41;; movement commands. 41;; movement commands.
@@ -144,7 +144,7 @@
144;; this command be added to the global keymap. 144;; this command be added to the global keymap.
145;; 145;;
146;; follow-recenter C-c . C-l 146;; follow-recenter C-c . C-l
147;; Place the point in the center of the middle window, 147;; Place point in the center of the middle window,
148;; or a specified number of lines from either top or bottom. 148;; or a specified number of lines from either top or bottom.
149;; 149;;
150;; follow-switch-to-buffer C-c . b 150;; follow-switch-to-buffer C-c . b
@@ -202,6 +202,7 @@
202;;; Code: 202;;; Code:
203 203
204(require 'easymenu) 204(require 'easymenu)
205(eval-when-compile (require 'cl-lib))
205 206
206;;; Variables 207;;; Variables
207 208
@@ -390,7 +391,7 @@ virtual window. This is accomplished by two main techniques:
390 This means that whenever one window is moved, all the 391 This means that whenever one window is moved, all the
391 others will follow. (Hence the name Follow mode.) 392 others will follow. (Hence the name Follow mode.)
392 393
393* Should the point (cursor) end up outside a window, another 394* Should point (cursor) end up outside a window, another
394 window displaying that point is selected, if possible. This 395 window displaying that point is selected, if possible. This
395 makes it possible to walk between windows using normal cursor 396 makes it possible to walk between windows using normal cursor
396 movement commands. 397 movement commands.
@@ -532,7 +533,7 @@ This is to be called by `comint-postoutput-scroll-to-bottom'."
532 (select-window win) 533 (select-window win)
533 (goto-char pos) 534 (goto-char pos)
534 (setq follow-windows-start-end-cache nil) 535 (setq follow-windows-start-end-cache nil)
535 (follow-adjust-window win pos) 536 (follow-adjust-window win)
536 (unless is-selected 537 (unless is-selected
537 (select-window selected) 538 (select-window selected)
538 (set-buffer buffer)))))) 539 (set-buffer buffer))))))
@@ -744,12 +745,9 @@ contains only windows in the same frame as WIN. If WIN is nil,
744it defaults to the selected window." 745it defaults to the selected window."
745 (unless (window-live-p win) 746 (unless (window-live-p win)
746 (setq win (selected-window))) 747 (setq win (selected-window)))
747 (let ((buffer (window-buffer win)) 748 (let ((windows (get-buffer-window-list
748 windows) 749 (window-buffer win) 'no-minibuf (window-frame win))))
749 (dolist (w (window-list (window-frame win) 'no-minibuf win)) 750 (sort windows #'follow--window-sorter)))
750 (if (eq (window-buffer w) buffer)
751 (push w windows)))
752 (sort windows 'follow--window-sorter)))
753 751
754(defun follow-split-followers (windows &optional win) 752(defun follow-split-followers (windows &optional win)
755 "Split WINDOWS into two sets: predecessors and successors. 753 "Split WINDOWS into two sets: predecessors and successors.
@@ -847,7 +845,7 @@ returned by `follow-windows-start-end'."
847 (setq win-start-end (cdr win-start-end))) 845 (setq win-start-end (cdr win-start-end)))
848 result)) 846 result))
849 847
850;; Check if the point is visible in all windows. (So that 848;; Check if point is visible in all windows. (So that
851;; no one will be recentered.) 849;; no one will be recentered.)
852 850
853(defun follow-point-visible-all-windows-p (win-start-end) 851(defun follow-point-visible-all-windows-p (win-start-end)
@@ -866,7 +864,7 @@ returned by `follow-windows-start-end'."
866;; will lead to a redisplay of the screen later on. 864;; will lead to a redisplay of the screen later on.
867;; 865;;
868;; This is used with the first window in a follow chain. The reason 866;; This is used with the first window in a follow chain. The reason
869;; is that we want to detect that the point is outside the window. 867;; is that we want to detect that point is outside the window.
870;; (Without the update, the start of the window will move as the 868;; (Without the update, the start of the window will move as the
871;; user presses BackSpace, and the other window redisplay routines 869;; user presses BackSpace, and the other window redisplay routines
872;; will move the start of the window in the wrong direction.) 870;; will move the start of the window in the wrong direction.)
@@ -898,7 +896,7 @@ Return the selected window."
898 896
899;; Lets select a window showing the end. Make sure we only select it if 897;; Lets select a window showing the end. Make sure we only select it if
900;; it wasn't just moved here. (I.e. M-> shall not unconditionally place 898;; it wasn't just moved here. (I.e. M-> shall not unconditionally place
901;; the point in the selected window.) 899;; point in the selected window.)
902;; 900;;
903;; (Compatibility kludge: in Emacs `window-end' is equal to `point-max'; 901;; (Compatibility kludge: in Emacs `window-end' is equal to `point-max';
904;; in XEmacs, it is equal to `point-max + 1'. Should I really bother 902;; in XEmacs, it is equal to `point-max + 1'. Should I really bother
@@ -924,10 +922,10 @@ Return the selected window."
924 win)) 922 win))
925 923
926 924
927;; Select a window that will display the point if the windows would 925;; Select a window that will display point if the windows would
928;; be redisplayed with the first window fixed. This is useful for 926;; be redisplayed with the first window fixed. This is useful for
929;; example when the user has pressed return at the bottom of a window 927;; example when the user has pressed return at the bottom of a window
930;; as the point is not visible in any window. 928;; as point is not visible in any window.
931 929
932(defun follow-select-if-visible-from-first (dest windows) 930(defun follow-select-if-visible-from-first (dest windows)
933 "Try to select one of WINDOWS without repositioning the topmost window. 931 "Try to select one of WINDOWS without repositioning the topmost window.
@@ -969,7 +967,7 @@ Otherwise, return nil."
969 967
970(defun follow-redisplay (&optional windows win preserve-win) 968(defun follow-redisplay (&optional windows win preserve-win)
971 "Reposition the WINDOWS around WIN. 969 "Reposition the WINDOWS around WIN.
972Should the point be too close to the roof we redisplay everything 970Should point be too close to the roof we redisplay everything
973from the top. WINDOWS should contain a list of windows to 971from the top. WINDOWS should contain a list of windows to
974redisplay; it is assumed that WIN is a member of the list. 972redisplay; it is assumed that WIN is a member of the list.
975Should WINDOWS be nil, the windows displaying the 973Should WINDOWS be nil, the windows displaying the
@@ -1124,158 +1122,157 @@ non-first windows in Follow mode."
1124 (with-current-buffer (window-buffer win) 1122 (with-current-buffer (window-buffer win)
1125 (unless (and (symbolp this-command) 1123 (unless (and (symbolp this-command)
1126 (get this-command 'follow-mode-use-cache)) 1124 (get this-command 'follow-mode-use-cache))
1127 (setq follow-windows-start-end-cache nil)))
1128 (follow-adjust-window win (point)))))
1129
1130(defun follow-adjust-window (win dest)
1131 ;; Adjust the window WIN and its followers.
1132 (with-current-buffer (window-buffer win)
1133 (when (and follow-mode
1134 (not (window-minibuffer-p win)))
1135 (let* ((windows (follow-all-followers win))
1136 (win-start-end (progn
1137 (follow-update-window-start (car windows))
1138 (follow-windows-start-end windows)))
1139 (aligned (follow-windows-aligned-p win-start-end))
1140 (visible (follow-pos-visible dest win win-start-end))
1141 selected-window-up-to-date)
1142 (unless (and aligned visible)
1143 (setq follow-windows-start-end-cache nil)) 1125 (setq follow-windows-start-end-cache nil))
1126 (follow-adjust-window win)))))
1144 1127
1145 ;; Select a window to display point. 1128(defun follow-adjust-window (win)
1146 (unless follow-internal-force-redisplay 1129 ;; Adjust the window WIN and its followers.
1147 (if (eq dest (point-max)) 1130 (cl-assert (eq (window-buffer win) (current-buffer)))
1148 ;; Be careful at point-max: the display can be aligned 1131 (when (and follow-mode
1149 ;; while DEST can be visible in several windows. 1132 (not (window-minibuffer-p win)))
1150 (cond 1133 (let* ((dest (point))
1151 ;; Select the current window, but only when the display 1134 (windows (follow-all-followers win))
1152 ;; is correct. (When inserting characters in a tail 1135 (win-start-end (progn
1153 ;; window, the display is not correct, as they are 1136 (follow-update-window-start (car windows))
1154 ;; shown twice.) 1137 (follow-windows-start-end windows)))
1155 ;; 1138 (aligned (follow-windows-aligned-p win-start-end))
1156 ;; Never stick to the current window after a deletion. 1139 (visible (follow-pos-visible dest win win-start-end))
1157 ;; Otherwise, when typing `DEL' in a window showing 1140 selected-window-up-to-date)
1158 ;; only the end of the file, a character would be 1141 (unless (and aligned visible)
1159 ;; removed from the window above, which is very 1142 (setq follow-windows-start-end-cache nil))
1160 ;; unintuitive. 1143
1161 ((and visible 1144 ;; Select a window to display point.
1162 aligned 1145 (unless follow-internal-force-redisplay
1163 (not (memq this-command 1146 (if (eq dest (point-max))
1164 '(backward-delete-char 1147 ;; Be careful at point-max: the display can be aligned
1165 delete-backward-char 1148 ;; while DEST can be visible in several windows.
1166 backward-delete-char-untabify 1149 (cond
1167 kill-region)))) 1150 ;; Select the current window, but only when the display
1168 (follow-debug-message "Max: same")) 1151 ;; is correct. (When inserting characters in a tail
1169 ;; If the end is visible, and the window doesn't 1152 ;; window, the display is not correct, as they are
1170 ;; seems like it just has been moved, select it. 1153 ;; shown twice.)
1171 ((follow-select-if-end-visible win-start-end) 1154 ;;
1172 (follow-debug-message "Max: end visible") 1155 ;; Never stick to the current window after a deletion.
1173 (setq visible t aligned nil) 1156 ;; Otherwise, when typing `DEL' in a window showing
1174 (goto-char dest)) 1157 ;; only the end of the file, a character would be
1175 ;; Just show the end... 1158 ;; removed from the window above, which is very
1176 (t 1159 ;; unintuitive.
1177 (follow-debug-message "Max: default") 1160 ((and visible
1178 (select-window (car (last windows))) 1161 aligned
1179 (goto-char dest) 1162 (not (memq this-command
1180 (setq visible nil aligned nil))) 1163 '(backward-delete-char
1181 1164 delete-backward-char
1182 ;; We're not at the end, here life is much simpler. 1165 backward-delete-char-untabify
1183 (cond 1166 kill-region))))
1184 ;; This is the normal case! 1167 (follow-debug-message "Max: same"))
1185 ;; It should be optimized for speed. 1168 ;; If the end is visible, and the window doesn't
1186 ((and visible aligned) 1169 ;; seems like it just has been moved, select it.
1187 (follow-debug-message "same")) 1170 ((follow-select-if-end-visible win-start-end)
1188 ;; Pick a position in any window. If the display is ok, 1171 (follow-debug-message "Max: end visible")
1189 ;; this picks the `correct' window. 1172 (setq visible t aligned nil)
1190 ((follow-select-if-visible dest win-start-end) 1173 (goto-char dest))
1191 (follow-debug-message "visible") 1174 ;; Just show the end...
1192 (goto-char dest) 1175 (t
1193 ;; Perform redisplay, in case line is partially visible. 1176 (follow-debug-message "Max: default")
1194 (setq visible nil)) 1177 (select-window (car (last windows)))
1195 ;; Not visible anywhere else, lets pick this one. 1178 (goto-char dest)
1196 (visible 1179 (setq visible nil aligned nil)))
1197 (follow-debug-message "visible in selected.")) 1180
1198 ;; If DEST is before the first window start, select the 1181 ;; We're not at the end, here life is much simpler.
1199 ;; first window. 1182 (cond
1200 ((< dest (nth 1 (car win-start-end))) 1183 ;; This is the normal case!
1201 (follow-debug-message "before first") 1184 ;; It should be optimized for speed.
1202 (select-window (car windows)) 1185 ((and visible aligned)
1203 (goto-char dest) 1186 (follow-debug-message "same"))
1204 (setq visible nil aligned nil)) 1187 ;; Pick a position in any window. If the display is ok,
1205 ;; If we can position the cursor without moving the first 1188 ;; this picks the `correct' window.
1206 ;; window, do it. This is the case that catches `RET' at 1189 ((follow-select-if-visible dest win-start-end)
1207 ;; the bottom of a window. 1190 (follow-debug-message "visible")
1208 ((follow-select-if-visible-from-first dest windows) 1191 (goto-char dest)
1209 (follow-debug-message "Below first") 1192 ;; Perform redisplay, in case line is partially visible.
1210 (setq visible t aligned t)) 1193 (setq visible nil))
1211 ;; None of the above. Stick to the selected window. 1194 ;; Not visible anywhere else, lets pick this one.
1212 (t 1195 (visible
1213 (follow-debug-message "None") 1196 (follow-debug-message "visible in selected."))
1214 (setq visible nil aligned nil)))) 1197 ;; If DEST is before the first window start, select the
1215 1198 ;; first window.
1216 ;; If a new window was selected, make sure that the old is 1199 ((< dest (nth 1 (car win-start-end)))
1217 ;; not scrolled when the point is outside the window. 1200 (follow-debug-message "before first")
1218 (unless (eq win (selected-window)) 1201 (select-window (car windows))
1219 (let ((p (window-point win))) 1202 (goto-char dest)
1220 (set-window-start win (window-start win) nil) 1203 (setq visible nil aligned nil))
1221 (set-window-point win p)))) 1204 ;; If we can position the cursor without moving the first
1222 1205 ;; window, do it. This is the case that catches `RET' at
1223 (unless visible 1206 ;; the bottom of a window.
1224 ;; If point may not be visible in the selected window, 1207 ((follow-select-if-visible-from-first dest windows)
1225 ;; perform a redisplay; this ensures scrolling. 1208 (follow-debug-message "Below first")
1226 (let ((opoint (point))) 1209 (setq visible t aligned t))
1227 (redisplay) 1210 ;; None of the above. Stick to the selected window.
1228 ;; If this `redisplay' moved point, we got clobbered by a 1211 (t
1229 ;; previous call to `set-window-start'. Try again. 1212 (follow-debug-message "None")
1230 (when (/= (point) opoint) 1213 (setq visible nil aligned nil))))
1231 (goto-char opoint) 1214
1232 (redisplay))) 1215 ;; If a new window was selected, make sure that the old is
1233 1216 ;; not scrolled when point is outside the window.
1234 (setq selected-window-up-to-date t) 1217 (unless (eq win (selected-window))
1235 (follow-avoid-tail-recenter) 1218 (let ((p (window-point win)))
1236 (setq win-start-end (follow-windows-start-end windows) 1219 (set-window-start win (window-start win) nil)
1237 follow-windows-start-end-cache nil 1220 (set-window-point win p))))
1238 aligned nil)) 1221
1239 1222 (unless visible
1240 ;; Now redraw the windows around the selected window. 1223 ;; If point may not be visible in the selected window,
1241 (unless (and (not follow-internal-force-redisplay) 1224 ;; perform a redisplay; this ensures scrolling.
1242 (or aligned 1225 (let ((opoint (point)))
1243 (follow-windows-aligned-p win-start-end)) 1226 (redisplay)
1244 (follow-point-visible-all-windows-p win-start-end)) 1227 ;; If this `redisplay' moved point, we got clobbered by a
1245 (setq follow-internal-force-redisplay nil) 1228 ;; previous call to `set-window-start'. Try again.
1246 (follow-redisplay windows (selected-window) 1229 (when (/= (point) opoint)
1247 selected-window-up-to-date) 1230 (goto-char opoint)
1248 (setq win-start-end (follow-windows-start-end windows) 1231 (redisplay)))
1249 follow-windows-start-end-cache nil) 1232
1250 ;; The point can ends up in another window when DEST is at 1233 (setq selected-window-up-to-date t)
1251 ;; the beginning of the buffer and the selected window is 1234 (follow-avoid-tail-recenter)
1252 ;; not the first. It can also happen when long lines are 1235 (setq win-start-end (follow-windows-start-end windows)
1253 ;; used and there is a big difference between the width of 1236 follow-windows-start-end-cache nil
1254 ;; the windows. (When scrolling one line in a wide window 1237 aligned nil))
1255 ;; which will cause a move larger that an entire small 1238
1256 ;; window.) 1239 ;; Now redraw the windows around the selected window.
1257 (unless (follow-pos-visible dest win win-start-end) 1240 (unless (and (not follow-internal-force-redisplay)
1258 (follow-select-if-visible dest win-start-end) 1241 (or aligned
1259 (goto-char dest))) 1242 (follow-windows-aligned-p win-start-end))
1260 1243 (follow-point-visible-all-windows-p win-start-end))
1261 ;; If the region is visible, make it look good when spanning 1244 (setq follow-internal-force-redisplay nil)
1262 ;; multiple windows. 1245 (follow-redisplay windows (selected-window)
1263 1246 selected-window-up-to-date)
1264 ;; FIXME: Why not use `use-region-p' here? 1247 (setq win-start-end (follow-windows-start-end windows)
1265 (when (region-active-p) 1248 follow-windows-start-end-cache nil)
1266 (follow-maximize-region 1249 ;; Point can end up in another window when DEST is at
1267 (selected-window) windows win-start-end))) 1250 ;; the beginning of the buffer and the selected window is
1268 1251 ;; not the first. It can also happen when long lines are
1269 ;; Whether or not the buffer was in follow mode, update windows 1252 ;; used and there is a big difference between the width of
1270 ;; displaying the tail so that Emacs won't recenter them. 1253 ;; the windows. (When scrolling one line in a wide window
1271 (follow-avoid-tail-recenter)))) 1254 ;; which will cause a move larger that an entire small
1255 ;; window.)
1256 (unless (follow-pos-visible dest win win-start-end)
1257 (follow-select-if-visible dest win-start-end)
1258 (goto-char dest)))
1259
1260 ;; If the region is visible, make it look good when spanning
1261 ;; multiple windows.
1262 (when (region-active-p)
1263 (follow-maximize-region
1264 (selected-window) windows win-start-end)))
1265
1266 ;; Whether or not the buffer was in follow mode, update windows
1267 ;; displaying the tail so that Emacs won't recenter them.
1268 (follow-avoid-tail-recenter)))
1272 1269
1273;;; The region 1270;;; The region
1274 1271
1275;; Tries to make the highlighted area representing the region look 1272;; Tries to make the highlighted area representing the region look
1276;; good when spanning several windows. 1273;; good when spanning several windows.
1277;; 1274;;
1278;; Not perfect, as the point can't be placed at window end, only at 1275;; Not perfect, as point can't be placed at window end, only at
1279;; end-1. This will highlight a little bit in windows above 1276;; end-1. This will highlight a little bit in windows above
1280;; the current. 1277;; the current.
1281 1278