unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Search minibuffer history
@ 2007-07-09 20:59 Juri Linkov
  2007-07-10  5:38 ` Richard Stallman
  0 siblings, 1 reply; 14+ messages in thread
From: Juri Linkov @ 2007-07-09 20:59 UTC (permalink / raw)
  To: emacs-devel

Two years ago I implemented a feature that allows isearch to search
elements in the minibuffer history.  It works exactly as the incremental
search implemented in the GNU readline library used in shells like bash etc.
After typing C-r it displays the isearch prompt to show that isearch is
active and to indicate the state of the search.  After reaching the first
history element (when searching in the backward direction) the search wraps
to the last history element and vice versa.  When the search fails it
displays the error message and the failed search string.  I tried many
different implementations and now I am completely satisfied by the
described above.

This feature was warmly welcomed but its installation was postponed
due to the feature freeze.  Now I submit it again:

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	9 Jul 2007 20:57:33 -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,1471 ----
    ;; 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 the minibuffer history
+ (add-hook 'minibuffer-setup-hook 'minibuffer-history-isearch-setup)
+ 
+ (defvar minibuffer-history-isearch-prefix-overlay)
+ (make-variable-buffer-local 'minibuffer-history-isearch-prefix-overlay)
+ 
+ (defun minibuffer-history-isearch-setup ()
+   (add-hook 'isearch-mode-hook 'minibuffer-history-isearch-start nil t)
+   (add-hook 'isearch-mode-end-hook 'minibuffer-history-isearch-end nil t)
+   (set (make-local-variable 'isearch-search-fun-function)
+        'minibuffer-history-isearch-search)
+   (set (make-local-variable 'isearch-wrap-function)
+        'minibuffer-history-isearch-wrap)
+   (set (make-local-variable 'isearch-push-state-function)
+        'minibuffer-history-isearch-push-state))
+ 
+ (defun minibuffer-history-isearch-start ()
+   (setq minibuffer-history-isearch-prefix-overlay
+ 	(make-overlay (point-min) (minibuffer-prompt-end)))
+   (overlay-put minibuffer-history-isearch-prefix-overlay
+ 	       'display (isearch-message-prefix))
+   (overlay-put minibuffer-history-isearch-prefix-overlay 'evaporate t))
+ 
+ (defun minibuffer-history-isearch-end ()
+   (delete-overlay minibuffer-history-isearch-prefix-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 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)))
+ 		    (overlay-put minibuffer-history-isearch-prefix-overlay
+ 				 'display (isearch-message-prefix))
+                     (point))
+                 (error nil)))))))))
+ 
+ (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))
+ 
  \f
  ;Put this on C-x u, so we can force that rather than C-_ into startup msg
  (defalias 'advertised-undo 'undo)

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	9 Jul 2007 20:55:11 -0000
***************
*** 1924,1930 ****
                isearch-message)
  	    (isearch-message-suffix c-q-hack ellipsis)
  	    )))
!     (if c-q-hack
  	m
        (let ((message-log-max nil))
  	(message "%s" m)))))
--- 1928,1934 ----
                isearch-message)
  	    (isearch-message-suffix c-q-hack ellipsis)
  	    )))
!     (if (or c-q-hack (and (minibufferp) isearch-success (not isearch-error)))
  	m
        (let ((message-log-max nil))
  	(message "%s" m)))))
***************
*** 1944,1949 ****
--- 1948,1954 ----
  		   (if isearch-adjusted "pending " "")
  		   (if (and isearch-wrapped
  			    (not isearch-wrap-function)
+ 			    (not isearch-search-fun-function)
  			    (if isearch-forward
  				(> (point) isearch-opoint)
  			      (< (point) isearch-opoint)))

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-09 20:59 Search minibuffer history Juri Linkov
@ 2007-07-10  5:38 ` Richard Stallman
  2007-07-10 13:14   ` Juri Linkov
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Stallman @ 2007-07-10  5:38 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

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?

				(not isearch-wrap-function)
    + 			    (not isearch-search-fun-function)
				(if isearch-forward

What's the reasoning that shows this is generally correct?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-10  5:38 ` Richard Stallman
@ 2007-07-10 13:14   ` Juri Linkov
  2007-07-10 22:01     ` Richard Stallman
  0 siblings, 1 reply; 14+ messages in thread
From: Juri Linkov @ 2007-07-10 13:14 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

> 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))
+ 
  \f
  ;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/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-10 13:14   ` Juri Linkov
@ 2007-07-10 22:01     ` Richard Stallman
  2007-07-10 22:31       ` Juri Linkov
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Stallman @ 2007-07-10 22:01 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

Your code still needs a lot more comments.
Every function and every variable should have a comment,
and long functions should have an explanation of each part.

    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.

I see the point of this, but if the isearch prompt is not displayed
at all, how can the user understand the search?

Perhaps the right thing to do is to make the minibuffer taller
so as to make room to display the search prompt after the minibuffer.
That would require C-level changes, but maybe not too hard.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-10 22:01     ` Richard Stallman
@ 2007-07-10 22:31       ` Juri Linkov
  2007-07-11 21:04         ` Richard Stallman
  2007-07-11 21:04         ` Richard Stallman
  0 siblings, 2 replies; 14+ messages in thread
From: Juri Linkov @ 2007-07-10 22:31 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

> Your code still needs a lot more comments.
> Every function and every variable should have a comment,
> and long functions should have an explanation of each part.

I surely will add more comments as well as write changes to etc/NEWS and
the Emacs Manual once the implementation reaches its final state.

>     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.
>
> I see the point of this, but if the isearch prompt is not displayed
> at all, how can the user understand the search?

The isearch prompt is displayed over the original prompt which is not
essential at the short time of searching in the minibuffer.  The original
prompt gets restored immediately once the search finishes in the minibuffer.

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-10 22:31       ` Juri Linkov
@ 2007-07-11 21:04         ` Richard Stallman
  2007-07-11 22:55           ` Juri Linkov
  2007-07-11 21:04         ` Richard Stallman
  1 sibling, 1 reply; 14+ messages in thread
From: Richard Stallman @ 2007-07-11 21:04 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

    I surely will add more comments as well as write changes to etc/NEWS and
    the Emacs Manual once the implementation reaches its final state.

Please write the comments now -- we don't want to install it without them.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-10 22:31       ` Juri Linkov
  2007-07-11 21:04         ` Richard Stallman
@ 2007-07-11 21:04         ` Richard Stallman
  1 sibling, 0 replies; 14+ messages in thread
From: Richard Stallman @ 2007-07-11 21:04 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

    > I see the point of this, but if the isearch prompt is not displayed
    > at all, how can the user understand the search?

    The isearch prompt is displayed over the original prompt which is not
    essential at the short time of searching in the minibuffer.

If I understand that right, it is ok.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-11 21:04         ` Richard Stallman
@ 2007-07-11 22:55           ` Juri Linkov
  2007-07-12 21:23             ` Richard Stallman
  0 siblings, 1 reply; 14+ messages in thread
From: Juri Linkov @ 2007-07-11 22:55 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

> Please write the comments now -- we don't want to install it without them.

Below is a new patch with added comprehensive comments necessary to
understand how this feature works (I suppose that docstrings are not needed,
since new minibuffer-specific functions and variables are purely internal
and are not intended for calling directly by the user).

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	11 Jul 2007 22:50:40 -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.
***************
*** 1381,1386 ****
--- 1385,1506 ----
    ;; the buffer; this should be 0 for normal buffers.
    (1- (minibuffer-prompt-end)))
  \f
+ ;; 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 ()
+   (if minibuffer-history-isearch-message-overlay
+       (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
+ 	     ;; Use standard functions to search within minibuffer text
+              (cond
+               (isearch-regexp
+                (if isearch-forward 're-search-forward 're-search-backward))
+               (t
+                (if isearch-forward 'search-forward 'search-backward))))
+ 	    found)
+ 	;; Avoid lazy-highlighting matches in the minibuffer prompt when
+ 	;; searching forward.  Lazy-highlight calls this lambda with the
+ 	;; bound arg, so skip the minibuffer prompt.
+ 	(if (and bound isearch-forward (< (point) (minibuffer-prompt-end)))
+ 	    (goto-char (minibuffer-prompt-end)))
+         (or
+ 	 ;; 1. First try searching in the initial minibuffer text
+ 	 (funcall search-fun string
+ 		  (if isearch-forward bound (minibuffer-prompt-end))
+ 		  noerror)
+ 	 ;; 2. If the above search fails, start putting next/prev history
+ 	 ;; elements in the minibuffer successively, and search the string
+ 	 ;; in them.  Do this only when bound is nil (i.e. not while
+ 	 ;; lazy-highlighting search strings in the current minibuffer text).
+ 	 (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))
+ 		   ;; After putting the next/prev history element, search
+ 		   ;; the string in them again, until next-history-element
+ 		   ;; or previous-history-element raises an error at the
+ 		   ;; beginning/end of history.
+ 		   (setq found (funcall search-fun string
+ 					(unless isearch-forward
+ 					  ;; For backward search, don't search
+ 					  ;; in the minibuffer prompt
+ 					  (minibuffer-prompt-end))
+ 					noerror)))
+ 		 ;; Return point of the new search result
+ 		 (point))
+ 	     ;; Return nil when next(prev)-history-element fails
+ 	     (error nil)))))))))
+ 
+ (defun minibuffer-history-isearch-message (&optional c-q-hack ellipsis)
+   (if (not (and (minibufferp) isearch-success (not isearch-error)))
+       ;; Use standard function `isearch-message' when not in the minibuffer,
+       ;; or search fails, or has an error (like incomplete regexp).
+       ;; This function overwrites minibuffer text with isearch message,
+       ;; so it's possible to see what is wrong in the search string.
+       (isearch-message c-q-hack ellipsis)
+     ;; Otherwise, put the overlay with the standard isearch prompt over
+     ;; the initial minibuffer prompt.
+     (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))
+     ;; And clear any previous isearch message.
+     (message "")))
+ 
+ (defun minibuffer-history-isearch-wrap ()
+   ;; When `minibuffer-history-isearch-search' fails on reaching the
+   ;; beginning/end of the history, wrap the search to the first/last
+   ;; minibuffer history element.
+   (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 ()
+   ;; Save minibuffer-history-position to the additional state parameter.
+   `(lambda (cmd)
+      (minibuffer-history-isearch-pop-state cmd ,minibuffer-history-position)))
+ 
+ (defun minibuffer-history-isearch-pop-state (cmd hist-pos)
+   ;; Go to the history element by the absolute history position `hist-pos'.
+   (next-history-element 0 hist-pos))
+ 
+ \f
  ;Put this on C-x u, so we can force that rather than C-_ into startup msg
  (defalias 'advertised-undo 'undo)

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	11 Jul 2007 22:50:17 -0000
***************
*** 164,169 ****
--- 164,173 ----
  (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.
+ If nil, use `isearch-message'.")
+ 
  (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))))
--- 725,733 ----
  	   (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)))
--- 2035,2043 ----
  
  (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)))

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-11 22:55           ` Juri Linkov
@ 2007-07-12 21:23             ` Richard Stallman
  2007-07-15 20:04               ` Juri Linkov
  0 siblings, 1 reply; 14+ messages in thread
From: Richard Stallman @ 2007-07-12 21:23 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

    Below is a new patch with added comprehensive comments necessary to
    understand how this feature works (I suppose that docstrings are not needed,
    since new minibuffer-specific functions and variables are purely internal
    and are not intended for calling directly by the user).

It is best to give every function and variable a doc string, even if
it is for internal use only.  Your new functions, including
`minibuffer-history-isearch-setup', `minibuffer-history-isearch-end',
`minibuffer-history-isearch-search' and the rest need overall
documentation.  It has to be either a comment or a doc string, but it
may as well be a doc string.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-12 21:23             ` Richard Stallman
@ 2007-07-15 20:04               ` Juri Linkov
  2007-07-16 15:05                 ` Stefan Monnier
  2007-07-16 15:49                 ` Richard Stallman
  0 siblings, 2 replies; 14+ messages in thread
From: Juri Linkov @ 2007-07-15 20:04 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

> It is best to give every function and variable a doc string, even if
> it is for internal use only.  Your new functions, including
> `minibuffer-history-isearch-setup', `minibuffer-history-isearch-end',
> `minibuffer-history-isearch-search' and the rest need overall
> documentation.  It has to be either a comment or a doc string, but it
> may as well be a doc string.

Is it OK to install the patch with doc strings?  A copy of the patch is below:

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	13 Jul 2007 16:57:44 -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.
***************
*** 1381,1386 ****
--- 1385,1520 ----
    ;; the buffer; this should be 0 for normal buffers.
    (1- (minibuffer-prompt-end)))
  \f
+ ;; 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 up a minibuffer for using isearch to search the minibuffer history.
+ Intended to be added to `minibuffer-setup-hook'."
+   (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 ()
+   "Clean up the minibuffer after terminating an incremental search."
+   (if minibuffer-history-isearch-message-overlay
+       (delete-overlay minibuffer-history-isearch-message-overlay)))
+ 
+ (defun minibuffer-history-isearch-search ()
+   "Return the function for isearch that searches in the minibuffer history."
+   (cond
+    (isearch-word
+     (if isearch-forward 'word-search-forward 'word-search-backward))
+    (t
+     (lambda (string bound noerror)
+       (let ((search-fun
+ 	     ;; Use standard functions to search within minibuffer text
+              (cond
+               (isearch-regexp
+                (if isearch-forward 're-search-forward 're-search-backward))
+               (t
+                (if isearch-forward 'search-forward 'search-backward))))
+ 	    found)
+ 	;; Avoid lazy-highlighting matches in the minibuffer prompt when
+ 	;; searching forward.  Lazy-highlight calls this lambda with the
+ 	;; bound arg, so skip the minibuffer prompt.
+ 	(if (and bound isearch-forward (< (point) (minibuffer-prompt-end)))
+ 	    (goto-char (minibuffer-prompt-end)))
+         (or
+ 	 ;; 1. First try searching in the initial minibuffer text
+ 	 (funcall search-fun string
+ 		  (if isearch-forward bound (minibuffer-prompt-end))
+ 		  noerror)
+ 	 ;; 2. If the above search fails, start putting next/prev history
+ 	 ;; elements in the minibuffer successively, and search the string
+ 	 ;; in them.  Do this only when bound is nil (i.e. not while
+ 	 ;; lazy-highlighting search strings in the current minibuffer text).
+ 	 (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))
+ 		   ;; After putting the next/prev history element, search
+ 		   ;; the string in them again, until next-history-element
+ 		   ;; or previous-history-element raises an error at the
+ 		   ;; beginning/end of history.
+ 		   (setq found (funcall search-fun string
+ 					(unless isearch-forward
+ 					  ;; For backward search, don't search
+ 					  ;; in the minibuffer prompt
+ 					  (minibuffer-prompt-end))
+ 					noerror)))
+ 		 ;; Return point of the new search result
+ 		 (point))
+ 	     ;; Return nil when next(prev)-history-element fails
+ 	     (error nil)))))))))
+ 
+ (defun minibuffer-history-isearch-message (&optional c-q-hack ellipsis)
+   "Display the minibuffer history search prompt.
+ It is either the standard isearch prompt displayed by `isearch-message'
+ in case of a search error, or an overlay with the isearch prompt displayed
+ over the original minibuffer prompt in case of successful search."
+   (if (not (and (minibufferp) isearch-success (not isearch-error)))
+       ;; Use standard function `isearch-message' when not in the minibuffer,
+       ;; or search fails, or has an error (like incomplete regexp).
+       ;; This function overwrites minibuffer text with isearch message,
+       ;; so it's possible to see what is wrong in the search string.
+       (isearch-message c-q-hack ellipsis)
+     ;; Otherwise, put the overlay with the standard isearch prompt over
+     ;; the initial minibuffer prompt.
+     (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))
+     ;; And clear any previous isearch message.
+     (message "")))
+ 
+ (defun minibuffer-history-isearch-wrap ()
+   "Wrap the minibuffer history search when search is failed.
+ Move point to the first history element for a forward search,
+ or to the last history element for a backward search."
+   (unless isearch-word
+     ;; When `minibuffer-history-isearch-search' fails on reaching the
+     ;; beginning/end of the history, wrap the search to the first/last
+     ;; minibuffer history element.
+     (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 ()
+   "Save a function restoring the state of minibuffer history search.
+ Save `minibuffer-history-position' to the additional state parameter
+ in the search status stack."
+   `(lambda (cmd)
+      (minibuffer-history-isearch-pop-state cmd ,minibuffer-history-position)))
+ 
+ (defun minibuffer-history-isearch-pop-state (cmd hist-pos)
+   "Restore the minibuffer history search state.
+ Go to the history element by the absolute history position `hist-pos'."
+   (next-history-element 0 hist-pos))
+ 
+ \f
  ;Put this on C-x u, so we can force that rather than C-_ into startup msg
  (defalias 'advertised-undo 'undo)

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	13 Jul 2007 16:56:55 -0000
***************
*** 164,169 ****
--- 164,173 ----
  (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.
+ If nil, use `isearch-message'.")
+ 
  (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))))
--- 725,733 ----
  	   (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)))
--- 2038,2046 ----
  
  (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)))

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-15 20:04               ` Juri Linkov
@ 2007-07-16 15:05                 ` Stefan Monnier
  2007-07-16 20:54                   ` Juri Linkov
  2007-07-16 15:49                 ` Richard Stallman
  1 sibling, 1 reply; 14+ messages in thread
From: Stefan Monnier @ 2007-07-16 15:05 UTC (permalink / raw)
  To: Juri Linkov; +Cc: rms, emacs-devel

> ! (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."

Am I the only to find the above interface to be .... ugly?
I'd rather have a function `next-history-element-internal' which takes the
NARG and then a command `next-history-element' which takes the N arg and
calls next-history-element-internal.


        Stefan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-15 20:04               ` Juri Linkov
  2007-07-16 15:05                 ` Stefan Monnier
@ 2007-07-16 15:49                 ` Richard Stallman
  2007-07-21 18:17                   ` Juri Linkov
  1 sibling, 1 reply; 14+ messages in thread
From: Richard Stallman @ 2007-07-16 15:49 UTC (permalink / raw)
  To: Juri Linkov; +Cc: emacs-devel

It is getting pretty good now, but some of these doc strings need
clarification.

    + (defun minibuffer-history-isearch-end ()
    +   "Clean up the minibuffer after terminating an incremental search."

That doc string needs to identify the usage more precisely.
This is not used after just any isearch, only after a specific kind.

    + (defun minibuffer-history-isearch-search ()
    +   "Return the function for isearch that searches in the minibuffer history."

I can't understand that sentence.

    + (defun minibuffer-history-isearch-message (&optional c-q-hack ellipsis)
    +   "Display the minibuffer history search prompt.
    + It is either the standard isearch prompt displayed by `isearch-message'
    + in case of a search error, or an overlay with the isearch prompt displayed
    + over the original minibuffer prompt in case of successful search."

I don't understand "it is either" in that doc string.
Are you talking about _how_ this function does its job?
If so, please say that explicitly.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-16 15:05                 ` Stefan Monnier
@ 2007-07-16 20:54                   ` Juri Linkov
  0 siblings, 0 replies; 14+ messages in thread
From: Juri Linkov @ 2007-07-16 20:54 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: rms, emacs-devel

>> ! (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."
>
> Am I the only to find the above interface to be .... ugly?
> I'd rather have a function `next-history-element-internal' which takes the
> NARG and then a command `next-history-element' which takes the N arg and
> calls next-history-element-internal.

I think the `-internal' suffix doesn't describe exactly what a new
function should do.  These two interfaces differ only in a way how they
navigate the minibuffer history.  The current function navigates by an
offset relative to the minibuffer position, but a new function should
navigate the history by the absolute position.  So this function should
have a name without the `next-' prefix.  I propose the name
`minibuffer-history-element' and the argument `nabs'.  Below is a patch
created with `-w -b' switches to better show diffs without changes
in whitespace.

Index: lisp/simple.el
===================================================================
RCS file: /sources/emacs/emacs/lisp/simple.el,v
retrieving revision 1.865
diff -c -w -b -r1.865 simple.el
*** lisp/simple.el	7 Jul 2007 11:17:51 -0000	1.865
--- lisp/simple.el	16 Jul 2007 20:52:18 -0000
***************
*** 1300,1322 ****
  
  (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)
  		 (null minibuffer-text-before-history))
  	    (setq minibuffer-text-before-history
  		  (minibuffer-contents-no-properties)))
! 	(if (< narg minimum)
  	    (if minibuffer-default
  		(error "End of history; no next item")
  	      (error "End of history; no default available")))
! 	(if (> narg (length (symbol-value minibuffer-history-variable)))
  	    (error "Beginning of history; no preceding item"))
  	(unless (memq last-command '(next-history-element
  				     previous-history-element))
--- 1300,1319 ----
  
  (defvar minibuffer-temporary-goal-position nil)
  
! (defun minibuffer-history-element (nabs)
!   "Puts element of the minibuffer history in the minibuffer.
! The argument NABS specifies the absolute history position."
!   (let ((minimum (if minibuffer-default -1 0))
  	elt minibuffer-returned-to-present)
      (if (and (zerop minibuffer-history-position)
  	     (null minibuffer-text-before-history))
  	(setq minibuffer-text-before-history
  	      (minibuffer-contents-no-properties)))
!     (if (< nabs minimum)
  	(if minibuffer-default
  	    (error "End of history; no next item")
  	  (error "End of history; no default available")))
!     (if (> nabs (length (symbol-value minibuffer-history-variable)))
  	(error "Beginning of history; no preceding item"))
      (unless (memq last-command '(next-history-element
  				 previous-history-element))
***************
*** 1327,1336 ****
  		       (t (point))))))
  	(goto-char (point-max))
  	(delete-minibuffer-contents)
! 	(setq minibuffer-history-position narg)
! 	(cond ((= narg -1)
  	       (setq elt minibuffer-default))
! 	      ((= narg 0)
  	       (setq elt (or minibuffer-text-before-history ""))
  	       (setq minibuffer-returned-to-present t)
  	       (setq minibuffer-text-before-history nil))
--- 1324,1333 ----
  		   (t (point))))))
      (goto-char (point-max))
      (delete-minibuffer-contents)
!     (setq minibuffer-history-position nabs)
!     (cond ((= nabs -1)
  	   (setq elt minibuffer-default))
! 	  ((= nabs 0)
  	   (setq elt (or minibuffer-text-before-history ""))
  	   (setq minibuffer-returned-to-present t)
  	   (setq minibuffer-text-before-history nil))
***************
*** 1342,1354 ****
  	     (let ((print-level nil))
  	       (prin1-to-string elt))
  	   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.
--- 1339,1359 ----
  	 (let ((print-level nil))
  	   (prin1-to-string elt))
         elt))
!     (goto-char (or minibuffer-temporary-goal-position (point-max)))))
! 
! (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)
!       (minibuffer-history-element (- minibuffer-history-position n))))
  
  (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")
!   (or (zerop n)
!       (minibuffer-history-element (+ minibuffer-history-position n))))
  
  (defun next-complete-history-element (n)
    "Get next history element which completes the minibuffer before the point.
***************
*** 1381,1386 ****
--- 1386,1521 ----
    ;; the buffer; this should be 0 for normal buffers.
    (1- (minibuffer-prompt-end)))
  \f
+ ;; 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 up a minibuffer for using isearch to search the minibuffer history.
+ Intended to be added to `minibuffer-setup-hook'."
+   (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 ()
+   "Clean up the minibuffer after terminating an incremental search."
+   (if minibuffer-history-isearch-message-overlay
+       (delete-overlay minibuffer-history-isearch-message-overlay)))
+ 
+ (defun minibuffer-history-isearch-search ()
+   "Return the function for isearch that searches in the minibuffer history."
+   (cond
+    (isearch-word
+     (if isearch-forward 'word-search-forward 'word-search-backward))
+    (t
+     (lambda (string bound noerror)
+       (let ((search-fun
+ 	     ;; Use standard functions to search within minibuffer text
+              (cond
+               (isearch-regexp
+                (if isearch-forward 're-search-forward 're-search-backward))
+               (t
+                (if isearch-forward 'search-forward 'search-backward))))
+ 	    found)
+ 	;; Avoid lazy-highlighting matches in the minibuffer prompt when
+ 	;; searching forward.  Lazy-highlight calls this lambda with the
+ 	;; bound arg, so skip the minibuffer prompt.
+ 	(if (and bound isearch-forward (< (point) (minibuffer-prompt-end)))
+ 	    (goto-char (minibuffer-prompt-end)))
+         (or
+ 	 ;; 1. First try searching in the initial minibuffer text
+ 	 (funcall search-fun string
+ 		  (if isearch-forward bound (minibuffer-prompt-end))
+ 		  noerror)
+ 	 ;; 2. If the above search fails, start putting next/prev history
+ 	 ;; elements in the minibuffer successively, and search the string
+ 	 ;; in them.  Do this only when bound is nil (i.e. not while
+ 	 ;; lazy-highlighting search strings in the current minibuffer text).
+ 	 (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))
+ 		   ;; After putting the next/prev history element, search
+ 		   ;; the string in them again, until next-history-element
+ 		   ;; or previous-history-element raises an error at the
+ 		   ;; beginning/end of history.
+ 		   (setq found (funcall search-fun string
+ 					(unless isearch-forward
+ 					  ;; For backward search, don't search
+ 					  ;; in the minibuffer prompt
+ 					  (minibuffer-prompt-end))
+ 					noerror)))
+ 		 ;; Return point of the new search result
+ 		 (point))
+ 	     ;; Return nil when next(prev)-history-element fails
+ 	     (error nil)))))))))
+ 
+ (defun minibuffer-history-isearch-message (&optional c-q-hack ellipsis)
+   "Display the minibuffer history search prompt.
+ It is either the standard isearch prompt displayed by `isearch-message'
+ in case of a search error, or an overlay with the isearch prompt displayed
+ over the original minibuffer prompt in case of successful search."
+   (if (not (and (minibufferp) isearch-success (not isearch-error)))
+       ;; Use standard function `isearch-message' when not in the minibuffer,
+       ;; or search fails, or has an error (like incomplete regexp).
+       ;; This function overwrites minibuffer text with isearch message,
+       ;; so it's possible to see what is wrong in the search string.
+       (isearch-message c-q-hack ellipsis)
+     ;; Otherwise, put the overlay with the standard isearch prompt over
+     ;; the initial minibuffer prompt.
+     (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))
+     ;; And clear any previous isearch message.
+     (message "")))
+ 
+ (defun minibuffer-history-isearch-wrap ()
+   "Wrap the minibuffer history search when search is failed.
+ Move point to the first history element for a forward search,
+ or to the last history element for a backward search."
+   (unless isearch-word
+     ;; When `minibuffer-history-isearch-search' fails on reaching the
+     ;; beginning/end of the history, wrap the search to the first/last
+     ;; minibuffer history element.
+     (if isearch-forward
+ 	(minibuffer-history-element (length (symbol-value minibuffer-history-variable)))
+       (minibuffer-history-element 0))
+     (setq isearch-success t))
+   (goto-char (if isearch-forward (minibuffer-prompt-end) (point-max))))
+ 
+ (defun minibuffer-history-isearch-push-state ()
+   "Save a function restoring the state of minibuffer history search.
+ Save `minibuffer-history-position' to the additional state parameter
+ in the search status stack."
+   `(lambda (cmd)
+      (minibuffer-history-isearch-pop-state cmd ,minibuffer-history-position)))
+ 
+ (defun minibuffer-history-isearch-pop-state (cmd hist-pos)
+   "Restore the minibuffer history search state.
+ Go to the history element by the absolute history position `hist-pos'."
+   (minibuffer-history-element hist-pos))
+ 
+ \f
  ;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/

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: Search minibuffer history
  2007-07-16 15:49                 ` Richard Stallman
@ 2007-07-21 18:17                   ` Juri Linkov
  0 siblings, 0 replies; 14+ messages in thread
From: Juri Linkov @ 2007-07-21 18:17 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

I'd like to install the following patch in the next few days if there are
no objections.

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	20 Jul 2007 20:06:24 -0000
***************
*** 1300,1354 ****
  
  (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)
! 		 (null minibuffer-text-before-history))
! 	    (setq minibuffer-text-before-history
! 		  (minibuffer-contents-no-properties)))
! 	(if (< narg minimum)
! 	    (if minibuffer-default
! 		(error "End of history; no next item")
! 	      (error "End of history; no default available")))
! 	(if (> narg (length (symbol-value minibuffer-history-variable)))
! 	    (error "Beginning of history; no preceding item"))
! 	(unless (memq last-command '(next-history-element
! 				     previous-history-element))
! 	  (let ((prompt-end (minibuffer-prompt-end)))
! 	    (set (make-local-variable 'minibuffer-temporary-goal-position)
! 		 (cond ((<= (point) prompt-end) prompt-end)
! 		       ((eobp) nil)
! 		       (t (point))))))
! 	(goto-char (point-max))
! 	(delete-minibuffer-contents)
! 	(setq minibuffer-history-position narg)
! 	(cond ((= narg -1)
! 	       (setq elt minibuffer-default))
! 	      ((= narg 0)
! 	       (setq elt (or minibuffer-text-before-history ""))
! 	       (setq minibuffer-returned-to-present t)
! 	       (setq minibuffer-text-before-history nil))
! 	      (t (setq elt (nth (1- minibuffer-history-position)
! 				(symbol-value minibuffer-history-variable)))))
! 	(insert
! 	 (if (and (eq minibuffer-history-sexp-flag (minibuffer-depth))
! 		  (not minibuffer-returned-to-present))
! 	     (let ((print-level nil))
! 	       (prin1-to-string elt))
! 	   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.
--- 1300,1360 ----
  
  (defvar minibuffer-temporary-goal-position nil)
  
+ (defun goto-minibuffer-history-element (nabs)
+   "Puts element of the minibuffer history in the minibuffer.
+ The argument NABS specifies the absolute history position."
+   (interactive "p")
+   (let ((minimum (if minibuffer-default -1 0))
+ 	elt minibuffer-returned-to-present)
+     (if (and (zerop minibuffer-history-position)
+ 	     (null minibuffer-text-before-history))
+ 	(setq minibuffer-text-before-history
+ 	      (minibuffer-contents-no-properties)))
+     (if (< nabs minimum)
+ 	(if minibuffer-default
+ 	    (error "End of history; no next item")
+ 	  (error "End of history; no default available")))
+     (if (> nabs (length (symbol-value minibuffer-history-variable)))
+ 	(error "Beginning of history; no preceding item"))
+     (unless (memq last-command '(next-history-element
+ 				 previous-history-element))
+       (let ((prompt-end (minibuffer-prompt-end)))
+ 	(set (make-local-variable 'minibuffer-temporary-goal-position)
+ 	     (cond ((<= (point) prompt-end) prompt-end)
+ 		   ((eobp) nil)
+ 		   (t (point))))))
+     (goto-char (point-max))
+     (delete-minibuffer-contents)
+     (setq minibuffer-history-position nabs)
+     (cond ((= nabs -1)
+ 	   (setq elt minibuffer-default))
+ 	  ((= nabs 0)
+ 	   (setq elt (or minibuffer-text-before-history ""))
+ 	   (setq minibuffer-returned-to-present t)
+ 	   (setq minibuffer-text-before-history nil))
+ 	  (t (setq elt (nth (1- minibuffer-history-position)
+ 			    (symbol-value minibuffer-history-variable)))))
+     (insert
+      (if (and (eq minibuffer-history-sexp-flag (minibuffer-depth))
+ 	      (not minibuffer-returned-to-present))
+ 	 (let ((print-level nil))
+ 	   (prin1-to-string elt))
+        elt))
+     (goto-char (or minibuffer-temporary-goal-position (point-max)))))
+ 
  (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)
!       (goto-minibuffer-history-element (- minibuffer-history-position n))))
  
  (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")
!   (or (zerop n)
!       (goto-minibuffer-history-element (+ minibuffer-history-position n))))
  
  (defun next-complete-history-element (n)
    "Get next history element which completes the minibuffer before the point.
***************
*** 1381,1386 ****
--- 1387,1523 ----
    ;; the buffer; this should be 0 for normal buffers.
    (1- (minibuffer-prompt-end)))
  \f
+ ;; 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 up a minibuffer for using isearch to search the minibuffer history.
+ Intended to be added to `minibuffer-setup-hook'."
+   (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 ()
+   "Clean up the minibuffer after terminating isearch in the minibuffer."
+   (if minibuffer-history-isearch-message-overlay
+       (delete-overlay minibuffer-history-isearch-message-overlay)))
+ 
+ (defun minibuffer-history-isearch-search ()
+   "Return the proper search function, for isearch in minibuffer history."
+   (cond
+    (isearch-word
+     (if isearch-forward 'word-search-forward 'word-search-backward))
+    (t
+     (lambda (string bound noerror)
+       (let ((search-fun
+ 	     ;; Use standard functions to search within minibuffer text
+              (cond
+               (isearch-regexp
+                (if isearch-forward 're-search-forward 're-search-backward))
+               (t
+                (if isearch-forward 'search-forward 'search-backward))))
+ 	    found)
+ 	;; Avoid lazy-highlighting matches in the minibuffer prompt when
+ 	;; searching forward.  Lazy-highlight calls this lambda with the
+ 	;; bound arg, so skip the minibuffer prompt.
+ 	(if (and bound isearch-forward (< (point) (minibuffer-prompt-end)))
+ 	    (goto-char (minibuffer-prompt-end)))
+         (or
+ 	 ;; 1. First try searching in the initial minibuffer text
+ 	 (funcall search-fun string
+ 		  (if isearch-forward bound (minibuffer-prompt-end))
+ 		  noerror)
+ 	 ;; 2. If the above search fails, start putting next/prev history
+ 	 ;; elements in the minibuffer successively, and search the string
+ 	 ;; in them.  Do this only when bound is nil (i.e. not while
+ 	 ;; lazy-highlighting search strings in the current minibuffer text).
+ 	 (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))
+ 		   ;; After putting the next/prev history element, search
+ 		   ;; the string in them again, until next-history-element
+ 		   ;; or previous-history-element raises an error at the
+ 		   ;; beginning/end of history.
+ 		   (setq found (funcall search-fun string
+ 					(unless isearch-forward
+ 					  ;; For backward search, don't search
+ 					  ;; in the minibuffer prompt
+ 					  (minibuffer-prompt-end))
+ 					noerror)))
+ 		 ;; Return point of the new search result
+ 		 (point))
+ 	     ;; Return nil when next(prev)-history-element fails
+ 	     (error nil)))))))))
+ 
+ (defun minibuffer-history-isearch-message (&optional c-q-hack ellipsis)
+   "Display the minibuffer history search prompt.
+ If there are no search errors, this function displays an overlay with
+ the isearch prompt which replaces the original minibuffer prompt.
+ Otherwise, it displays the standard isearch message returned from
+ `isearch-message'."
+   (if (not (and (minibufferp) isearch-success (not isearch-error)))
+       ;; Use standard function `isearch-message' when not in the minibuffer,
+       ;; or search fails, or has an error (like incomplete regexp).
+       ;; This function overwrites minibuffer text with isearch message,
+       ;; so it's possible to see what is wrong in the search string.
+       (isearch-message c-q-hack ellipsis)
+     ;; Otherwise, put the overlay with the standard isearch prompt over
+     ;; the initial minibuffer prompt.
+     (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))
+     ;; And clear any previous isearch message.
+     (message "")))
+ 
+ (defun minibuffer-history-isearch-wrap ()
+   "Wrap the minibuffer history search when search is failed.
+ Move point to the first history element for a forward search,
+ or to the last history element for a backward search."
+   (unless isearch-word
+     ;; When `minibuffer-history-isearch-search' fails on reaching the
+     ;; beginning/end of the history, wrap the search to the first/last
+     ;; minibuffer history element.
+     (if isearch-forward
+ 	(goto-minibuffer-history-element (length (symbol-value minibuffer-history-variable)))
+       (goto-minibuffer-history-element 0))
+     (setq isearch-success t))
+   (goto-char (if isearch-forward (minibuffer-prompt-end) (point-max))))
+ 
+ (defun minibuffer-history-isearch-push-state ()
+   "Save a function restoring the state of minibuffer history search.
+ Save `minibuffer-history-position' to the additional state parameter
+ in the search status stack."
+   `(lambda (cmd)
+      (minibuffer-history-isearch-pop-state cmd ,minibuffer-history-position)))
+ 
+ (defun minibuffer-history-isearch-pop-state (cmd hist-pos)
+   "Restore the minibuffer history search state.
+ Go to the history element by the absolute history position `hist-pos'."
+   (goto-minibuffer-history-element hist-pos))
+ 
+ \f
  ;Put this on C-x u, so we can force that rather than C-_ into startup msg
  (defalias 'advertised-undo 'undo)

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	20 Jul 2007 20:00:09 -0000
***************
*** 164,169 ****
--- 164,173 ----
  (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.
+ If nil, use `isearch-message'.")
+ 
  (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))))
--- 725,733 ----
  	   (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)))
--- 2051,2059 ----
  
  (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)))

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

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2007-07-21 18:17 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-07-09 20:59 Search minibuffer history Juri Linkov
2007-07-10  5:38 ` Richard Stallman
2007-07-10 13:14   ` Juri Linkov
2007-07-10 22:01     ` Richard Stallman
2007-07-10 22:31       ` Juri Linkov
2007-07-11 21:04         ` Richard Stallman
2007-07-11 22:55           ` Juri Linkov
2007-07-12 21:23             ` Richard Stallman
2007-07-15 20:04               ` Juri Linkov
2007-07-16 15:05                 ` Stefan Monnier
2007-07-16 20:54                   ` Juri Linkov
2007-07-16 15:49                 ` Richard Stallman
2007-07-21 18:17                   ` Juri Linkov
2007-07-11 21:04         ` Richard Stallman

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).