unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Alan Mackenzie <acm@muc.de>
Subject: Re: Request for enhancement: Scrolling (etc.) in incremental search.
Date: Wed, 22 Oct 2003 08:09:58 +0000 (GMT)	[thread overview]
Message-ID: <Pine.LNX.3.96.1031022080631.272D-200000@acm.acm> (raw)
In-Reply-To: <Pine.LNX.3.96.1031021215907.178G-600000@acm.acm>

[-- Attachment #1: Type: TEXT/PLAIN, Size: 588 bytes --]



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)
>acm@muc.de


[-- Attachment #2: isearch.1.222.acm.el.diff --]
[-- Type: TEXT/PLAIN, Size: 12317 bytes --]

*** 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 (acm@muc.de), 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

[-- Attachment #3: Type: text/plain, Size: 141 bytes --]

_______________________________________________
Emacs-devel mailing list
Emacs-devel@gnu.org
http://mail.gnu.org/mailman/listinfo/emacs-devel

  reply	other threads:[~2003-10-22  8:09 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-10-21 22:03 Request for enhancement: Scrolling (etc.) in incremental search Alan Mackenzie
2003-10-22  8:09 ` Alan Mackenzie [this message]
2003-10-23  9:23 ` Richard Stallman
2003-10-23 21:48   ` Alan Mackenzie
2003-10-24 23:24     ` Richard Stallman
2003-10-27  9:09       ` Alan Mackenzie
2003-11-10  6:49     ` Juri Linkov
     [not found] <E18kfaI-0007iR-00@fencepost.gnu.org>
2003-02-26 13:36 ` Alan Mackenzie
2003-03-01  2:26   ` Richard Stallman
     [not found] <it1e3b.75.ln@acm.acm>
2003-02-25 16:57 ` Richard Stallman
2003-02-25 22:37 ` Kim F. Storm
2003-02-26 10:57   ` Alan Mackenzie

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Pine.LNX.3.96.1031022080631.272D-200000@acm.acm \
    --to=acm@muc.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).