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

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