[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Request for enhancement: Scrolling (etc.) in incremental search.
From: |
Alan Mackenzie |
Subject: |
Re: Request for enhancement: Scrolling (etc.) in incremental search. |
Date: |
Wed, 22 Oct 2003 08:09:58 +0000 (GMT) |
On Tue, 21 Oct 2003, Alan Mackenzie wrote:
>In February, I submitted a patch to enable scrolling commands to be used
>from within isearch mode without aborting the current search.
....
>Here is an (almost) complete version. To enable this facility, set the
>customizable variable isearch-allow-scroll to a non-nil value. (It is
>set to nil by default.) The enclosed patch to search.texi explains how
>it works.
Sorry: One of my patch files, isearch.1.222.acm.el.diff, wasn't in
context format. It is now. Here it is again.
>--
>Alan Mackenzie (Munich, Germany)
>address@hidden
*** isearch.1.222.el Tue Sep 23 21:04:28 2003
--- isearch.1.222.acm.el Tue Oct 21 20:53:36 2003
***************
*** 1224,1241 ****
(goto-char isearch-barrier)))
(isearch-process-search-char last-command-char))
(defalias 'isearch-other-control-char 'isearch-other-meta-char)
! (defun isearch-other-meta-char ()
! "Exit the search normally and reread this key sequence.
! But only if `search-exit-option' is non-nil, the default.
! If it is the symbol `edit', the search string is edited in the minibuffer
! and the meta character is unread so that it applies to editing the string."
! (interactive)
! (let* ((key (this-command-keys))
(main-event (aref key 0))
! (keylist (listify-key-sequence key)))
(cond ((and (= (length key) 1)
(let ((lookup (lookup-key function-key-map key)))
(not (or (null lookup) (integerp lookup)
--- 1224,1355 ----
(goto-char isearch-barrier)))
(isearch-process-search-char last-command-char))
+ (defun isearch-unread-key-sequence (keylist)
+ "Unread the given key-sequence KEYLIST, being careful with scroll-bar or
+ mode-line events."
+ (cancel-kbd-macro-events)
+ (apply 'isearch-unread keylist)
+ ;; If the event was a scroll-bar or mode-line click, the event will have
+ ;; been prefixed by a symbol such as vertical-scroll-bar. We must remove
+ ;; it here, because this symbol will be attached to the event again next
+ ;; time it gets read by read-key-sequence.
+ ;;
+ ;; (Old comment from isearch-other-meta-char: "Note that we don't have to
+ ;; modify the event anymore in 21 because read_key_sequence no longer
+ ;; modifies events to produce fake prefix keys.")
+ (if (and (> (length keylist) 1)
+ (symbolp (car keylist))
+ (listp (cadr keylist))
+ (not (numberp (posn-point
+ (event-start (cadr keylist) )))))
+ (pop unread-command-events)))
+
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+ ;; scrolling within isearch-mode. Alan Mackenzie (address@hidden), 2003/2/24
+ ;;
+ ;; The idea here is that certain vertical scrolling commands (like C-l
+ ;; (recenter)) should be usable WITHIN isearch mode. For a command to be
+ ;; suitable, it must NOT alter the buffer, swap to another buffer or frame,
+ ;; tamper with isearch's state, or move point. It is unacceptable for the
+ ;; search string to be scrolled out of the current window. If a command
+ ;; attempts this, we scroll the text back again.
+ ;;
+ ;; Horizontal scrolling commands are currently not catered for.
+ ;;
+ ;; We implement this feature with a property called isearch-scroll. If a
+ ;; command's symbol has the value t for this property it is a scrolling
+ ;; command.
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+ (defcustom isearch-allow-scroll nil
+ "If non-nil, certain scrolling commands are allowed during incremental
search."
+ :type 'boolean
+ :group 'isearch)
+
+ (defun isearch-string-out-of-window (isearch-point)
+ "Is the search string currently outside of the window? Return nil if it's
+ completely visible, or if point is visible, together with as much of the
+ search string as will fit; 'above if we need to scroll the text downwards;
+ '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)))
+ start end) ; start and end of search string in buffer
+ (if isearch-forward
+ (setq end isearch-point start (or isearch-other-end isearch-point))
+ (setq start isearch-point end (or isearch-other-end isearch-point)))
+ (cond ((or (and (>= start w-start) (<= end w-end))
+ (if isearch-forward
+ (and (>= isearch-point w-L-1) (< isearch-point w-end)) ;
point on Line -1
+ (and (>= isearch-point w-start) (< isearch-point w-L1)))) ;
point on Line 0
+ nil)
+ ((and (< start w-start)
+ (< isearch-point w-L-1))
+ 'above)
+ (t 'below))))
+
+ (defun isearch-back-into-window (above isearch-point)
+ "Scroll the window to bring the search string back into view, restoring
+ point to ISEARCH-POINT in the process. ABOVE is t when the search string is
+ above the top of the window, nil when it is beneath the bottom."
+ (let (start end)
+ (if isearch-forward
+ (setq end isearch-point start (or isearch-other-end isearch-point))
+ (setq start isearch-point end (or isearch-other-end isearch-point)))
+ (if above
+ (progn
+ (goto-char start)
+ (recenter 0)
+ (when (>= isearch-point (window-end nil t))
+ (goto-char isearch-point)
+ (recenter -1)))
+ (goto-char end)
+ (recenter -1)
+ (when (< isearch-point (window-start))
+ (goto-char isearch-point)
+ (recenter 0))))
+ (goto-char isearch-point))
+
+ (defun isearch-reread-key-sequence-naturally (keylist)
+ "Reread the current key sequence KEYLIST with isearch-mode's own keymap
+ deactivated. Return the key sequence as a string/vector."
+ (isearch-unread-key-sequence keylist)
+ (let (overriding-terminal-local-map)
+ (read-key-sequence nil))) ; This will go through function-key-map, if
nec.
+
+ (defun isearch-lookup-scroll-key (key)
+ "If the supplied key sequence, KEY, is bound to a scrolling command, return
+ this command (always a symbol), otherwise nil."
+ (let* ((overriding-terminal-local-map nil)
+ (binding (key-binding key)))
+ (and binding (symbolp binding) (commandp binding)
+ (eq (get binding 'isearch-scroll) t)
+ binding)))
(defalias 'isearch-other-control-char 'isearch-other-meta-char)
! (defun isearch-other-meta-char (&optional arg)
! "See if the current key-sequence can be converted to something usable in
! isearch-mode, either by converting it with the function-key-map, downcasing a
! key with C-<upper case>, or finding a \"scrolling command\" bound to it. \(In
! the last case, we may have to read more events.\) If so, either unread the
! converted sequence or execute the command.
!
! Otherwise, if `search-exit-option' is non-nil (the default) unread the
! key-sequence and exit the search normally. If it is the symbol `edit', the
! search string is edited in the minibuffer and the meta character is unread so
! that it applies to editing the string.
!
! ARG is the prefix argument. It will be transmitted through to the scrolling
! command or to the command which exits isearch-mode."
! (interactive "P")
! (let* ((key (if current-prefix-arg ; not nec the same as ARG
! (substring (this-command-keys)
universal-argument-num-events)
! (this-command-keys)))
(main-event (aref key 0))
! (keylist (listify-key-sequence key))
! scroll-command isearch-point)
(cond ((and (= (length key) 1)
(let ((lookup (lookup-key function-key-map key)))
(not (or (null lookup) (integerp lookup)
***************
*** 1287,1309 ****
((eq search-exit-option 'edit)
(apply 'isearch-unread keylist)
(isearch-edit-string))
(search-exit-option
(let (window)
! (cancel-kbd-macro-events)
! (apply 'isearch-unread keylist)
!
! ;; Properly handle scroll-bar and mode-line clicks for
! ;; which a dummy prefix event was generated as (aref key
! ;; 0). Note that we don't have to modify the event
! ;; anymore in 21 because read_key_sequence no longer modifies
! ;; events to produce fake prefix keys.
! (when (and (> (length key) 1)
! (symbolp (aref key 0))
! (listp (aref key 1))
! (not (numberp (posn-point
! (event-start (aref key 1))))))
! (pop unread-command-events)
! (setq main-event (car unread-command-events)))
;; If we got a mouse click event, that event contains the
;; window clicked on. maybe it was read with the buffer
--- 1401,1427 ----
((eq search-exit-option 'edit)
(apply 'isearch-unread keylist)
(isearch-edit-string))
+ ;; Handle a scrolling function.
+ ((and isearch-allow-scroll
+ (progn (setq key (isearch-reread-key-sequence-naturally
keylist))
+ (setq keylist (listify-key-sequence key))
+ (setq main-event (aref key 0))
+ (setq scroll-command (isearch-lookup-scroll-key key))))
+ ;; From this point onwards, KEY, KEYLIST and MAIN-EVENT hold a
+ ;; complete key sequence, possibly as modified by function-key-map,
+ ;; not merely the one or two event fragment which invoked
+ ;; isearch-other-meta-char in the first place.
+ (setq isearch-point (point))
+ (setq prefix-arg arg)
+ (command-execute scroll-command)
+ (let ((ab-bel (isearch-string-out-of-window isearch-point)))
+ (if ab-bel
+ (isearch-back-into-window (eq ab-bel 'above) isearch-point)))
+ (isearch-update))
(search-exit-option
(let (window)
! (isearch-unread-key-sequence keylist)
! (setq main-event (car unread-command-events))
;; If we got a mouse click event, that event contains the
;; window clicked on. maybe it was read with the buffer
***************
*** 1333,1340 ****
(isearch-done)
(isearch-clean-overlays))
(isearch-done)
! (isearch-clean-overlays))))
! (t;; otherwise nil
(isearch-process-search-string key key)))))
(defun isearch-quote-char ()
--- 1451,1459 ----
(isearch-done)
(isearch-clean-overlays))
(isearch-done)
! (isearch-clean-overlays)
! (setq prefix-arg arg))))
! (t;; otherwise nil
(isearch-process-search-string key key)))))
(defun isearch-quote-char ()
***************
*** 1997,2002 ****
--- 2116,2122 ----
(defvar isearch-lazy-highlight-last-string nil)
(defvar isearch-lazy-highlight-window nil)
(defvar isearch-lazy-highlight-window-start nil)
+ (defvar isearch-lazy-highlight-window-end nil)
(defvar isearch-lazy-highlight-case-fold-search nil)
(defvar isearch-lazy-highlight-regexp nil)
***************
*** 2031,2042 ****
(not (eq isearch-lazy-highlight-regexp
isearch-regexp))
(not (= (window-start)
! isearch-lazy-highlight-window-start))))
;; something important did indeed change
(isearch-lazy-highlight-cleanup t) ;kill old loop & remove overlays
(when (not isearch-invalid-regexp)
(setq isearch-lazy-highlight-window (selected-window)
isearch-lazy-highlight-window-start (window-start)
isearch-lazy-highlight-start (point)
isearch-lazy-highlight-end (point)
isearch-lazy-highlight-last-string isearch-string
--- 2151,2165 ----
(not (eq isearch-lazy-highlight-regexp
isearch-regexp))
(not (= (window-start)
! isearch-lazy-highlight-window-start))
! (not (= (window-end) ; Window may have been split/joined.
! isearch-lazy-highlight-window-end))))
;; something important did indeed change
(isearch-lazy-highlight-cleanup t) ;kill old loop & remove overlays
(when (not isearch-invalid-regexp)
(setq isearch-lazy-highlight-window (selected-window)
isearch-lazy-highlight-window-start (window-start)
+ isearch-lazy-highlight-window-end (window-end)
isearch-lazy-highlight-start (point)
isearch-lazy-highlight-end (point)
isearch-lazy-highlight-last-string isearch-string