unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Juri Linkov <juri@jurta.org>
Cc: emacs-devel@gnu.org
Subject: Re: next-matching-history-element default [patch]
Date: Tue, 28 Dec 2004 03:28:34 +0200	[thread overview]
Message-ID: <871xdbnrct.fsf@jurta.org> (raw)
In-Reply-To: <E1CimCb-0003Hl-7j@fencepost.gnu.org> (Richard Stallman's message of "Sun, 26 Dec 2004 23:09:49 -0500")

Richard Stallman <rms@gnu.org> writes:
> Thanks.  I'll install that.

This indeed fixes the long-standing problem in `next-matching-history-element'
(I think the reason it was not fixed for a long time is that everyone
uses M-r, not M-s which finds nothing from the initial history position),
but I have a change I implemented three months ago that will depreciate
`previous-matching-history-element' (and `next-matching-history-element').

The change I propose is to use isearch to search the minibuffer history.
This way Emacs will provide an incremental search in the history in
the same way as shells using readline already provide.

The following patch sets the value of `isearch-search-fun-function' in
the minibuffer to a function similar to `Info-isearch-search' used to
search through Info multiple nodes.

This also requires three fixes in isearch.el to work better
in the case when isearch-search-fun-function is specified
and when isearch is used in the minibuffer.

Index: lisp/simple.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/simple.el,v
retrieving revision 1.674
diff -u -r1.674 simple.el
--- lisp/simple.el	27 Dec 2004 16:34:43 -0000	1.674
+++ lisp/simple.el	28 Dec 2004 00:52:57 -0000
@@ -1143,11 +1143,13 @@
 
 (defvar minibuffer-temporary-goal-position nil)
 
-(defun next-history-element (n)
-  "Insert the next element of the minibuffer history into the minibuffer."
+(defun next-history-element (n &optional narg)
+  "Insert Nth next element of the minibuffer history into the minibuffer.
+The optional argument NARG overrides the N argument and specifies the
+absolute history position instead of relative position specified by N."
   (interactive "p")
-  (or (zerop n)
-      (let ((narg (- minibuffer-history-position n))
+  (unless (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)
@@ -1221,6 +1221,64 @@
   ;; 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-isearch-initialize)
+
+(defun minibuffer-isearch-initialize ()
+  (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-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)))))
+        (or (funcall search-fun string
+                     (or bound (unless isearch-forward (minibuffer-prompt-end)))
+                     noerror)
+            (unless bound
+              (condition-case nil
+                  (progn
+                    (while (not (funcall
+                                 search-fun string
+                                 (unless isearch-forward (minibuffer-prompt-end))
+                                 noerror))
+                      (cond
+                       (isearch-forward
+                        (next-history-element 1)
+                        (goto-char (minibuffer-prompt-end)))
+                       (t
+                        (previous-history-element 1)
+                        (goto-char (point-max)))))
+                    (point))
+                (error nil)))))))))
+
+(defun minibuffer-history-isearch-wrap ()
+  (if (not isearch-word)
+      (if isearch-forward
+          (next-history-element 0 (length (symbol-value minibuffer-history-variable)))
+        (next-history-element 0 0)))
+  (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: /cvsroot/emacs/emacs/lisp/isearch.el,v
retrieving revision 1.249
diff -u -r1.249 isearch.el
--- lisp/isearch.el	15 Dec 2004 10:08:51 -0000	1.249
+++ lisp/isearch.el	28 Dec 2004 00:59:44 -0000
@@ -1300,9 +1300,11 @@
       ;; Not regexp, not reverse, or no match at point.
       (if (and isearch-other-end (not isearch-adjusted))
 	  (goto-char (if isearch-forward isearch-other-end
-		       (min isearch-opoint
-			    isearch-barrier
-			    (1+ isearch-other-end)))))
+		       (if isearch-search-fun-function
+			   (1+ isearch-other-end)
+			 (min isearch-opoint
+			      isearch-barrier
+			      (1+ isearch-other-end))))))
       (isearch-search)
       ))
   (isearch-push-state)
@@ -1879,10 +1881,19 @@
               isearch-message)
 	    (isearch-message-suffix c-q-hack ellipsis)
 	    )))
-    (if c-q-hack
+    (if (or (and (minibuffer-window-active-p (selected-window))
+		 isearch-success
+		 (not isearch-invalid-regexp))
+	    c-q-hack)
 	m
       (let ((message-log-max nil))
-	(message "%s" m)))))
+	(message "%s" m)
+	(when (and (minibuffer-window-active-p (selected-window))
+		   (not isearch-invalid-regexp))
+	  (sit-for (or isearch-original-minibuffer-message-timeout
+		       minibuffer-message-timeout
+                       0))
+	  (message ""))))))
 
 (defun isearch-message-prefix (&optional c-q-hack ellipsis nonincremental)
   ;; If about to search, and previous search regexp was invalid,
@@ -1900,6 +1911,7 @@
 		   (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/

      reply	other threads:[~2004-12-28  1:28 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-12-25 21:08 next-matching-history-element default [patch] Kevin Ryde
2004-12-27  4:09 ` Richard Stallman
2004-12-28  1:28   ` Juri Linkov [this message]

Reply instructions:

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

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

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

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

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

  git send-email \
    --in-reply-to=871xdbnrct.fsf@jurta.org \
    --to=juri@jurta.org \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

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

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

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

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