emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Search minibuffer history


From: Juri Linkov
Subject: Re: Search minibuffer history
Date: Tue, 10 Jul 2007 16:14:46 +0300
User-agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1.50 (gnu/linux)

> Thanks for bringing this up again.  We should be able to install it soon,
> but first, the code needs a lot more comments.
>
>     !     (if (or c-q-hack (and (minibufferp) isearch-success (not 
> isearch-error)))
>
> What's the purpose of that new code?

This code prevents `isearch-message' from overwriting the minibuffer text
with the isearch prompt.  Without this condition `isearch-message' calls
`message' that puts the isearch prompt over the minibuffer content, so the
user can't see the search string highlighted in the minibuffer.

However, your question helped me to realize that `isearch-message' is not
a proper place to put minibuffer-specific code.  A general solution would
be to add a new function variable thats allows redefining `isearch-message'
with a specific function.  The patch below adds a new variable
`isearch-message-function' and redefines it in simple.el to the function
`minibuffer-history-isearch-message'.

>                               (not isearch-wrap-function)
>     +                             (not isearch-search-fun-function)
>                               (if isearch-forward
>
> What's the reasoning that shows this is generally correct?

The logic of adding the "Over(wrapped)" prefix is valid only for
searching a normal buffer since it compares point with the original
value isearch-opoint.  When applied to the minibuffer history search,
it could compare the current minibuffer history position with the
original one.  This requires implementing a minibuffer-specific code,
but really I don't find it worthy of adding another isearch variable to
allow overriding the logic of displaying the "Over" prefix.  A new patch
below doesn't modify this behavior, and it is good enough for the
minibuffer history search:

Index: lisp/isearch.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/isearch.el,v
retrieving revision 1.298
diff -c -r1.298 isearch.el
*** lisp/isearch.el     9 Jul 2007 14:45:01 -0000       1.298
--- lisp/isearch.el     10 Jul 2007 12:59:08 -0000
***************
*** 164,169 ****
--- 164,172 ----
  (defvar isearch-mode-end-hook-quit nil
    "Non-nil while running `isearch-mode-end-hook' if user quit the search.")
  
+ (defvar isearch-message-function nil
+   "Function to call to display the search prompt.")
+ 
  (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,
***************
*** 715,721 ****
           (null executing-kbd-macro))
        (progn
          (if (not (input-pending-p))
!             (isearch-message))
          (if (and isearch-slow-terminal-mode
                   (not (or isearch-small-window
                            (pos-visible-in-window-p))))
--- 724,732 ----
           (null executing-kbd-macro))
        (progn
          (if (not (input-pending-p))
!           (if isearch-message-function
!               (funcall isearch-message-function)
!             (isearch-message)))
          (if (and isearch-slow-terminal-mode
                   (not (or isearch-small-window
                            (pos-visible-in-window-p))))
***************
*** 2020,2026 ****
  
  (defun isearch-search ()
    ;; Do the search with the current search string.
!   (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)))
--- 2034,2042 ----
  
  (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)))

Index: lisp/simple.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/simple.el,v
retrieving revision 1.865
diff -c -r1.865 simple.el
*** lisp/simple.el      7 Jul 2007 11:17:51 -0000       1.865
--- lisp/simple.el      10 Jul 2007 12:09:54 -0000
***************
*** 1300,1311 ****
  
  (defvar minibuffer-temporary-goal-position nil)
  
! (defun next-history-element (n)
    "Puts next element of the minibuffer history in the minibuffer.
! With argument N, it uses the Nth following element."
    (interactive "p")
!   (or (zerop n)
!       (let ((narg (- minibuffer-history-position n))
            (minimum (if minibuffer-default -1 0))
            elt minibuffer-returned-to-present)
        (if (and (zerop minibuffer-history-position)
--- 1300,1313 ----
  
  (defvar minibuffer-temporary-goal-position nil)
  
! (defun next-history-element (n &optional narg)
    "Puts next element of the minibuffer history in the minibuffer.
! With argument N, it uses the Nth following element.
! The optional argument NARG overrides the argument N and specifies the
! absolute history position instead of relative position specified by N."
    (interactive "p")
!   (or (and (zerop n) (not narg))
!       (let ((narg (or narg (- minibuffer-history-position n)))
            (minimum (if minibuffer-default -1 0))
            elt minibuffer-returned-to-present)
        (if (and (zerop minibuffer-history-position)
***************
*** 1344,1354 ****
           elt))
        (goto-char (or minibuffer-temporary-goal-position (point-max))))))
  
! (defun previous-history-element (n)
    "Puts previous element of the minibuffer history in the minibuffer.
! With argument N, it uses the Nth previous element."
    (interactive "p")
!   (next-history-element (- n)))
  
  (defun next-complete-history-element (n)
    "Get next history element which completes the minibuffer before the point.
--- 1346,1358 ----
           elt))
        (goto-char (or minibuffer-temporary-goal-position (point-max))))))
  
! (defun previous-history-element (n &optional narg)
    "Puts previous element of the minibuffer history in the minibuffer.
! With argument N, it uses the Nth previous element.
! The optional argument NARG overrides the argument N and specifies the
! absolute history position instead of relative position specified by N."
    (interactive "p")
!   (next-history-element (- n) narg))
  
  (defun next-complete-history-element (n)
    "Get next history element which completes the minibuffer before the point.
***************
*** 1380,1385 ****
--- 1384,1477 ----
    ;; Return the width of everything before the field at the end of
    ;; the buffer; this should be 0 for normal buffers.
    (1- (minibuffer-prompt-end)))
+ 
+ ;; isearch minibuffer history
+ (add-hook 'minibuffer-setup-hook 'minibuffer-history-isearch-setup)
+ 
+ (defvar minibuffer-history-isearch-message-overlay)
+ (make-variable-buffer-local 'minibuffer-history-isearch-message-overlay)
+ 
+ (defun minibuffer-history-isearch-setup ()
+   (set (make-local-variable 'isearch-search-fun-function)
+        'minibuffer-history-isearch-search)
+   (set (make-local-variable 'isearch-message-function)
+        'minibuffer-history-isearch-message)
+   (set (make-local-variable 'isearch-wrap-function)
+        'minibuffer-history-isearch-wrap)
+   (set (make-local-variable 'isearch-push-state-function)
+        'minibuffer-history-isearch-push-state)
+   (add-hook 'isearch-mode-end-hook 'minibuffer-history-isearch-end nil t))
+ 
+ (defun minibuffer-history-isearch-end ()
+   (delete-overlay minibuffer-history-isearch-message-overlay))
+ 
+ (defun minibuffer-history-isearch-search ()
+   (cond
+    (isearch-word
+     (if isearch-forward 'word-search-forward 'word-search-backward))
+    (t
+     (lambda (string bound noerror)
+       (let ((search-fun
+              (cond
+               (isearch-regexp
+                (if isearch-forward 're-search-forward 're-search-backward))
+               (t
+                (if isearch-forward 'search-forward 'search-backward))))
+           found)
+       ;; Avoid lazy-highlighting minibuffer prompt
+       (if (and bound isearch-forward (< (point) (minibuffer-prompt-end)))
+           (goto-char (minibuffer-prompt-end)))
+         (or (funcall search-fun string
+                    (if isearch-forward bound (minibuffer-prompt-end))
+                      noerror)
+           ;; Search history unless lazy-highlighting
+             (unless bound
+               (condition-case nil
+                   (progn
+                     (while (not found)
+                       (cond (isearch-forward
+                            (next-history-element 1)
+                            (goto-char (minibuffer-prompt-end)))
+                           (t
+                            (previous-history-element 1)
+                            (goto-char (point-max))))
+                     (setq isearch-barrier (point) isearch-opoint (point))
+                     (setq found (funcall search-fun string
+                                          (unless isearch-forward
+                                            (minibuffer-prompt-end))
+                                          noerror)))
+                     (point))
+                 (error nil)))))))))
+ 
+ (defun minibuffer-history-isearch-message (&optional c-q-hack ellipsis)
+   (if (not (and (minibufferp) isearch-success (not isearch-error)))
+       (isearch-message c-q-hack ellipsis)
+     (if (overlayp minibuffer-history-isearch-message-overlay)
+       (move-overlay minibuffer-history-isearch-message-overlay
+                     (point-min) (minibuffer-prompt-end))
+       (setq minibuffer-history-isearch-message-overlay
+           (make-overlay (point-min) (minibuffer-prompt-end)))
+       (overlay-put minibuffer-history-isearch-message-overlay 'evaporate t))
+     (overlay-put minibuffer-history-isearch-message-overlay
+                'display (isearch-message-prefix c-q-hack ellipsis))
+     ;; Clear any previous isearch message
+     (message "")))
+ 
+ (defun minibuffer-history-isearch-wrap ()
+   (unless isearch-word
+     (if isearch-forward
+       (next-history-element 0 (length (symbol-value 
minibuffer-history-variable)))
+       (next-history-element 0 0))
+     (setq isearch-success t))
+   (goto-char (if isearch-forward (minibuffer-prompt-end) (point-max))))
+ 
+ (defun minibuffer-history-isearch-push-state ()
+   `(lambda (cmd)
+      (minibuffer-history-isearch-pop-state cmd ,minibuffer-history-position)))
+ 
+ (defun minibuffer-history-isearch-pop-state (cmd hist-pos)
+   (next-history-element 0 hist-pos))
+ 
  
  ;Put this on C-x u, so we can force that rather than C-_ into startup msg
  (defalias 'advertised-undo 'undo)

-- 
Juri Linkov
http://www.jurta.org/emacs/




reply via email to

[Prev in Thread] Current Thread [Next in Thread]