summaryrefslogtreecommitdiff
path: root/lisp/isearch.el
diff options
context:
space:
mode:
authorAlan Mackenzie <acm@muc.de>2015-11-11 12:02:48 +0000
committerAlan Mackenzie <acm@muc.de>2015-12-04 18:15:27 +0000
commit64c57303658f69b019c4599f8c960a5623855410 (patch)
treecf49a687ba1784eb52451ab02a5d99013c88caab /lisp/isearch.el
parent30f3432e9519f61882faa303e7851e761d2d18ea (diff)
downloademacs-64c57303658f69b019c4599f8c960a5623855410.tar.gz
First commit to scratch/follow. Make Isearch work with Follow Mode, etc.
doc/lispref/window.texi (Basic Windows): Add paragraph defining "Group of Windows" and new @defun selected-window-group. (Window Start and End): Describe new &optional parameter GROUP and ...-group-function for window-start, window-end, set-window-start, and pos-visible-in-window-p. (Textual Scrolling) Describe the same for recenter. doc/lispref/positions.texi (Screen Lines): Describe the same for move-to-window-line. src/window.c (Fwindow_start, Fwindow_end, Fset_window_start) (Fpos_visible_in_window_p, Frecenter, Fmove_to_window_line): To each, add ar new optional parameter "group". At the beginning of each, check whether the corresponding ...-group-function is set to a function, and if so execute this function in place of the normal processing. (syms_of_window): Define symbols for the six new variables below. (window-start-group-function, window-end-group-function) (set-window-start-group-function, recenter-group-function) (pos-visible-in-window-p-group-function, move-to-window-line-group-function): New permanent local buffer local variables. src/keyboard.c (Fposn_at_point): Add extra parameter in call to Fpos_visible_in_window_p. lisp/window.el (selected-window-group-function): New permanent local buffer local variable. (selected-window-group): New function. lisp/follow.el (follow-mode): Set the ...-group-function variables at mode enable, kill them at mode disable. Add/remove follow-after-change to/from after-change-functions. (follow-start-end-invalid): New variable. (follow-redisplay): Manipulate follow-start-end-invalid. (follow-after-change, follow-window-start, follow-window-end) (follow-set-window-start, follow-pos-visible-in-window-p) (follow-move-to-window-line, follow-sit-for): New functions. lisp/isearch.el (isearch-call-message): New macro. (isearch-update, with-isearch-suspended, isearch-del-char) (isearch-search-and-update, isearch-ring-adjust): Invoke above new macro. (with-isearch-suspended): Rearrange code such that isearch-call-message is invoked before point is moved. (isearch-message): Add comment about where point must be at function call. (isearch-search): Remove call to isearch-message. (isearch-lazy-highlight-window-group): New variable. (isearch-lazy-highlight-new-loop): Unconditionally start idle timer. Move the battery of tests to ... (isearch-lazy-highlight-maybe-new-loop): New function, started by idle timer. Note: (sit-for 0) is still called. (isearch-lazy-highlight-update): Check membership of isearch-lazy-highlight-window-group. Don't set the `window' overlay property. (isearch-update, isearch-done, isearch-string-out-of-window) (isearch-back-into-window, isearch-lazy-highlight-maybe-new-loop) (isearch-lazy-highlight-search, isearch-lazy-highlight-update) (isearch-lazy-highlight-update): Call the six amended primitives (see src/window.c above) with the new `group' argument set to t, to cooperate with Follow Mode.
Diffstat (limited to 'lisp/isearch.el')
-rw-r--r--lisp/isearch.el133
1 files changed, 80 insertions, 53 deletions
diff --git a/lisp/isearch.el b/lisp/isearch.el
index 8c98d36f4aa..39d573cc01f 100644
--- a/lisp/isearch.el
+++ b/lisp/isearch.el
@@ -177,6 +177,11 @@ is non-nil if the user quits the search.")
"Function to call to display the search prompt.
If nil, use function `isearch-message'.")
+(defmacro isearch-call-message (&optional cqh ellip)
+ `(if isearch-message-function
+ (funcall isearch-message-function ,cqh ,ellip)
+ (isearch-message ,cqh ,ellip)))
+
(defvar isearch-wrap-function nil
"Function to call to wrap the search when search is failed.
If nil, move point to the beginning of the buffer for a forward search,
@@ -978,12 +983,10 @@ The last thing it does is to run `isearch-update-post-hook'."
(null executing-kbd-macro))
(progn
(if (not (input-pending-p))
- (if isearch-message-function
- (funcall isearch-message-function)
- (isearch-message)))
+ (isearch-call-message))
(if (and isearch-slow-terminal-mode
(not (or isearch-small-window
- (pos-visible-in-window-p))))
+ (pos-visible-in-window-p nil nil nil t))))
(let ((found-point (point)))
(setq isearch-small-window t)
(move-to-window-line 0)
@@ -1004,7 +1007,7 @@ The last thing it does is to run `isearch-update-post-hook'."
(let ((current-scroll (window-hscroll))
visible-p)
(set-window-hscroll (selected-window) isearch-start-hscroll)
- (setq visible-p (pos-visible-in-window-p nil nil t))
+ (setq visible-p (pos-visible-in-window-p nil nil t t))
(if (or (not visible-p)
;; When point is not visible because of hscroll,
;; pos-visible-in-window-p returns non-nil, but
@@ -1058,7 +1061,7 @@ NOPUSH is t and EDIT is t."
(setq minibuffer-message-timeout isearch-original-minibuffer-message-timeout)
(isearch-dehighlight)
(lazy-highlight-cleanup lazy-highlight-cleanup)
- (let ((found-start (window-start))
+ (let ((found-start (window-start nil t))
(found-point (point)))
(when isearch-window-configuration
(set-window-configuration isearch-window-configuration)
@@ -1068,7 +1071,7 @@ NOPUSH is t and EDIT is t."
;; This has an annoying side effect of clearing the last_modiff
;; field of the window, which can cause unwanted scrolling,
;; so don't do it unless truly necessary.
- (set-window-start (selected-window) found-start t))))
+ (set-window-start (selected-window) found-start t t))))
(setq isearch-mode nil)
(if isearch-input-method-local-p
@@ -1299,13 +1302,6 @@ You can update the global isearch variables by setting new values to
(unwind-protect
(progn ,@body)
- ;; Set point at the start (end) of old match if forward (backward),
- ;; so after exiting minibuffer isearch resumes at the start (end)
- ;; of this match and can find it again.
- (if (and old-other-end (eq old-point (point))
- (eq isearch-forward isearch-new-forward))
- (goto-char old-other-end))
-
;; Always resume isearching by restarting it.
(isearch-mode isearch-forward
isearch-regexp
@@ -1318,7 +1314,17 @@ You can update the global isearch variables by setting new values to
isearch-message isearch-new-message
isearch-forward isearch-new-forward
isearch-regexp-function isearch-new-regexp-function
- isearch-case-fold-search isearch-new-case-fold))
+ isearch-case-fold-search isearch-new-case-fold)
+
+ ;; Restore the minibuffer message before moving point.
+ (isearch-call-message nil t)
+
+ ;; Set point at the start (end) of old match if forward (backward),
+ ;; so after exiting minibuffer isearch resumes at the start (end)
+ ;; of this match and can find it again.
+ (if (and old-other-end (eq old-point (point))
+ (eq isearch-forward isearch-new-forward))
+ (goto-char old-other-end)))
;; Empty isearch-string means use default.
(when (= 0 (length isearch-string))
@@ -1931,6 +1937,7 @@ If search string is empty, just beep."
(length isearch-string))))
isearch-message (mapconcat 'isearch-text-char-description
isearch-string "")))
+ (isearch-call-message nil t) ; Do this before moving point.
;; Use the isearch-other-end as new starting point to be able
;; to find the remaining part of the search string again.
;; This is like what `isearch-search-and-update' does,
@@ -2107,6 +2114,7 @@ With argument, add COUNT copies of the character."
(setq isearch-case-fold-search
(isearch-no-upper-case-p isearch-string isearch-regexp))))
;; Not regexp, not reverse, or no match at point.
+ (isearch-call-message nil t) ; Do this before moving point.
(if (and isearch-other-end (not isearch-adjusted))
(goto-char (if isearch-forward isearch-other-end
(min isearch-opoint
@@ -2273,10 +2281,12 @@ Return nil if it's completely visible, or if point is visible,
together with as much of the search string as will fit; the symbol
`above' if we need to scroll the text downwards; the symbol `below',
if upwards."
- (let ((w-start (window-start))
- (w-end (window-end nil t))
- (w-L1 (save-excursion (move-to-window-line 1) (point)))
- (w-L-1 (save-excursion (move-to-window-line -1) (point)))
+ (let ((w-start (window-start nil t))
+ (w-end (window-end nil t t))
+ (w-L1 (save-excursion
+ (save-selected-window (move-to-window-line 1 t) (point))))
+ (w-L-1 (save-excursion
+ (save-selected-window (move-to-window-line -1 t) (point))))
start end) ; start and end of search string in buffer
(if isearch-forward
(setq end isearch-point start (or isearch-other-end isearch-point))
@@ -2303,15 +2313,15 @@ the bottom."
(if above
(progn
(goto-char start)
- (recenter 0)
- (when (>= isearch-point (window-end nil t))
+ (recenter 0 t)
+ (when (>= isearch-point (window-end nil t t))
(goto-char isearch-point)
- (recenter -1)))
+ (recenter -1 t)))
(goto-char end)
- (recenter -1)
- (when (< isearch-point (window-start))
+ (recenter -1 t)
+ (when (< isearch-point (window-start nil t))
(goto-char isearch-point)
- (recenter 0))))
+ (recenter 0 t))))
(goto-char isearch-point))
(defvar isearch-pre-scroll-point nil)
@@ -2458,6 +2468,7 @@ Search is updated accordingly."
(isearch-ring-adjust1 advance)
(if search-ring-update
(progn
+ (isearch-call-message nil t)
(isearch-search)
(isearch-push-state)
(isearch-update))
@@ -2530,6 +2541,13 @@ If there is no completion possible, say so and continue searching."
(defun isearch-message (&optional c-q-hack ellipsis)
;; Generate and print the message string.
+
+ ;; N.B.: This function should always be called with point at the
+ ;; search point, because in certain (rare) circumstances, undesired
+ ;; scrolling can happen when point is elsewhere. These
+ ;; circumstances are when follow-mode is active, the search string
+ ;; spans two (or several) windows, and the message about to be
+ ;; displayed will cause the echo area to expand.
(let ((cursor-in-echo-area ellipsis)
(m isearch-message)
(fail-pos (isearch-fail-pos t)))
@@ -2723,9 +2741,6 @@ update the match data, and return point."
(defun isearch-search ()
;; Do the search with the current search string.
- (if isearch-message-function
- (funcall isearch-message-function nil t)
- (isearch-message nil t))
(if (and (eq isearch-case-fold-search t) search-upper-case)
(setq isearch-case-fold-search
(isearch-no-upper-case-p isearch-string isearch-regexp)))
@@ -3023,6 +3038,7 @@ since they have special meaning in a regexp."
(defvar isearch-lazy-highlight-timer nil)
(defvar isearch-lazy-highlight-last-string nil)
(defvar isearch-lazy-highlight-window nil)
+(defvar isearch-lazy-highlight-window-group nil)
(defvar isearch-lazy-highlight-window-start nil)
(defvar isearch-lazy-highlight-window-end nil)
(defvar isearch-lazy-highlight-case-fold-search nil)
@@ -3055,7 +3071,21 @@ is nil. This function is called when exiting an incremental search if
"22.1")
(defun isearch-lazy-highlight-new-loop (&optional beg end)
- "Cleanup any previous `lazy-highlight' loop and begin a new one.
+ "Set an idle timer, which will trigger a new `lazy-highlight' loop.
+BEG and END specify the bounds within which highlighting should
+occur. This is called when `isearch-update' is invoked (which
+can cause the search string to change or the window(s) to
+scroll). It is also used by other Emacs features. Do not start
+the loop when we are executing a keyboard macro."
+ (setq isearch-lazy-highlight-start-limit beg
+ isearch-lazy-highlight-end-limit end)
+ (when (null executing-kbd-macro)
+ (setq isearch-lazy-highlight-timer
+ (run-with-idle-timer lazy-highlight-initial-delay nil
+ 'isearch-lazy-highlight-maybe-new-loop))))
+
+(defun isearch-lazy-highlight-maybe-new-loop ()
+ "If needed cleanup any previous `lazy-highlight' loop and begin a new one.
BEG and END specify the bounds within which highlighting should occur.
This is called when `isearch-update' is invoked (which can cause the
search string to change or the window to scroll). It is also used
@@ -3064,8 +3094,8 @@ by other Emacs features."
(sit-for 0) ;make sure (window-start) is credible
(or (not (equal isearch-string
isearch-lazy-highlight-last-string))
- (not (eq (selected-window)
- isearch-lazy-highlight-window))
+ (not (memq (selected-window)
+ isearch-lazy-highlight-window-group))
(not (eq isearch-lazy-highlight-case-fold-search
isearch-case-fold-search))
(not (eq isearch-lazy-highlight-regexp
@@ -3076,9 +3106,9 @@ by other Emacs features."
isearch-lax-whitespace))
(not (eq isearch-lazy-highlight-regexp-lax-whitespace
isearch-regexp-lax-whitespace))
- (not (= (window-start)
+ (not (= (window-start nil t)
isearch-lazy-highlight-window-start))
- (not (= (window-end) ; Window may have been split/joined.
+ (not (= (window-end nil nil t) ; Window may have been split/joined.
isearch-lazy-highlight-window-end))
(not (eq isearch-forward
isearch-lazy-highlight-forward))
@@ -3086,16 +3116,15 @@ by other Emacs features."
(not (equal isearch-error
isearch-lazy-highlight-error))))
;; something important did indeed change
- (lazy-highlight-cleanup t) ;kill old loop & remove overlays
+ (lazy-highlight-cleanup t) ;kill old loop & remove overlays
(setq isearch-lazy-highlight-error isearch-error)
;; It used to check for `(not isearch-error)' here, but actually
;; lazy-highlighting might find matches to highlight even when
;; `isearch-error' is non-nil. (Bug#9918)
- (setq isearch-lazy-highlight-start-limit beg
- isearch-lazy-highlight-end-limit end)
(setq isearch-lazy-highlight-window (selected-window)
- isearch-lazy-highlight-window-start (window-start)
- isearch-lazy-highlight-window-end (window-end)
+ isearch-lazy-highlight-window-group (selected-window-group)
+ isearch-lazy-highlight-window-start (window-start nil t)
+ isearch-lazy-highlight-window-end (window-end nil nil t)
;; Start lazy-highlighting at the beginning of the found
;; match (`isearch-other-end'). If no match, use point.
;; One of the next two variables (depending on search direction)
@@ -3113,10 +3142,8 @@ by other Emacs features."
isearch-lazy-highlight-regexp-lax-whitespace isearch-regexp-lax-whitespace
isearch-lazy-highlight-regexp-function isearch-regexp-function
isearch-lazy-highlight-forward isearch-forward)
- (unless (equal isearch-string "")
- (setq isearch-lazy-highlight-timer
- (run-with-idle-timer lazy-highlight-initial-delay nil
- 'isearch-lazy-highlight-update)))))
+ (unless (equal isearch-string "")
+ (isearch-lazy-highlight-update))))
(defun isearch-lazy-highlight-search ()
"Search ahead for the next or previous match, for lazy highlighting.
@@ -3139,13 +3166,13 @@ Attempt to do the search exactly the way the pending Isearch would."
(+ isearch-lazy-highlight-start
;; Extend bound to match whole string at point
(1- (length isearch-lazy-highlight-last-string)))
- (window-end)))
+ (window-end nil nil t)))
(max (or isearch-lazy-highlight-start-limit (point-min))
(if isearch-lazy-highlight-wrapped
(- isearch-lazy-highlight-end
;; Extend bound to match whole string at point
(1- (length isearch-lazy-highlight-last-string)))
- (window-start))))))
+ (window-start nil t))))))
;; Use a loop like in `isearch-search'.
(while retry
(setq success (isearch-search-string
@@ -3169,7 +3196,7 @@ Attempt to do the search exactly the way the pending Isearch would."
(with-local-quit
(save-selected-window
(if (and (window-live-p isearch-lazy-highlight-window)
- (not (eq (selected-window) isearch-lazy-highlight-window)))
+ (not (memq (selected-window) isearch-lazy-highlight-window-group)))
(select-window isearch-lazy-highlight-window))
(save-excursion
(save-match-data
@@ -3189,12 +3216,12 @@ Attempt to do the search exactly the way the pending Isearch would."
(if isearch-lazy-highlight-forward
(if (= mb (if isearch-lazy-highlight-wrapped
isearch-lazy-highlight-start
- (window-end)))
+ (window-end nil nil t)))
(setq found nil)
(forward-char 1))
(if (= mb (if isearch-lazy-highlight-wrapped
isearch-lazy-highlight-end
- (window-start)))
+ (window-start nil t)))
(setq found nil)
(forward-char -1)))
@@ -3204,8 +3231,8 @@ Attempt to do the search exactly the way the pending Isearch would."
;; 1000 is higher than ediff's 100+,
;; but lower than isearch main overlay's 1001
(overlay-put ov 'priority 1000)
- (overlay-put ov 'face lazy-highlight-face)
- (overlay-put ov 'window (selected-window))))
+ (overlay-put ov 'face lazy-highlight-face)))
+ ;(overlay-put ov 'window (selected-window))))
;; Remember the current position of point for
;; the next call of `isearch-lazy-highlight-update'
;; when `lazy-highlight-max-at-a-time' is too small.
@@ -3221,12 +3248,12 @@ Attempt to do the search exactly the way the pending Isearch would."
(setq isearch-lazy-highlight-wrapped t)
(if isearch-lazy-highlight-forward
(progn
- (setq isearch-lazy-highlight-end (window-start))
+ (setq isearch-lazy-highlight-end (window-start nil t))
(goto-char (max (or isearch-lazy-highlight-start-limit (point-min))
- (window-start))))
- (setq isearch-lazy-highlight-start (window-end))
+ (window-start nil t))))
+ (setq isearch-lazy-highlight-start (window-end nil nil t))
(goto-char (min (or isearch-lazy-highlight-end-limit (point-max))
- (window-end))))))))
+ (window-end nil nil t))))))))
(unless nomore
(setq isearch-lazy-highlight-timer
(run-at-time lazy-highlight-interval nil