From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Juri Linkov Newsgroups: gmane.emacs.bugs Subject: bug#3746: M-r in comint mode should use isearch Date: Thu, 19 Nov 2009 19:30:43 +0200 Organization: JURTA Message-ID: <877htmbj2s.fsf@mail.jurta.org> References: <200907031326.n63DQfPA027629@godzilla.ics.uci.edu> <87zlblpajc.fsf@mail.jurta.org> <200907051503.n65F3fDv003169@godzilla.ics.uci.edu> <87ab3hxprg.fsf@mail.jurta.org> <200907070121.n671LmLt029754@godzilla.ics.uci.edu> <87skh8ynnm.fsf@mail.jurta.org> <200907082349.n68NnKRj025444@godzilla.ics.uci.edu> <87ljmxo5pw.fsf@mail.jurta.org> Reply-To: Juri Linkov , 3746@emacsbugs.donarmstrong.com NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-Trace: ger.gmane.org 1258654187 22272 80.91.229.12 (19 Nov 2009 18:09:47 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 19 Nov 2009 18:09:47 +0000 (UTC) Cc: 3746@emacsbugs.donarmstrong.com To: Dan Nicolaescu Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu Nov 19 19:09:40 2009 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1NBBRo-00017P-W3 for geb-bug-gnu-emacs@m.gmane.org; Thu, 19 Nov 2009 19:09:37 +0100 Original-Received: from localhost ([127.0.0.1]:45831 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NBBRo-0005uc-GY for geb-bug-gnu-emacs@m.gmane.org; Thu, 19 Nov 2009 13:09:36 -0500 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1NBBPm-00043T-OK for bug-gnu-emacs@gnu.org; Thu, 19 Nov 2009 13:07:30 -0500 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1NBBPh-0003yl-74 for bug-gnu-emacs@gnu.org; Thu, 19 Nov 2009 13:07:29 -0500 Original-Received: from [199.232.76.173] (port=35749 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1NBBPg-0003yR-KF for bug-gnu-emacs@gnu.org; Thu, 19 Nov 2009 13:07:24 -0500 Original-Received: from rzlab.ucr.edu ([138.23.92.77]:53455) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1NBBPf-0002oW-QJ for bug-gnu-emacs@gnu.org; Thu, 19 Nov 2009 13:07:24 -0500 Original-Received: from rzlab.ucr.edu (rzlab.ucr.edu [127.0.0.1]) by rzlab.ucr.edu (8.14.3/8.14.3/Debian-5) with ESMTP id nAJI7KAB026175; Thu, 19 Nov 2009 10:07:21 -0800 Original-Received: (from debbugs@localhost) by rzlab.ucr.edu (8.14.3/8.14.3/Submit) id nAJHt7Zu024201; Thu, 19 Nov 2009 09:55:07 -0800 Resent-Date: Thu, 19 Nov 2009 09:55:07 -0800 X-Loop: owner@emacsbugs.donarmstrong.com Resent-From: Juri Linkov Resent-To: bug-submit-list@donarmstrong.com Resent-CC: Emacs Bugs 2Resent-Date: Thu, 19 Nov 2009 17:55:07 +0000 Resent-Message-ID: Resent-Sender: owner@emacsbugs.donarmstrong.com X-Emacs-PR-Message: followup 3746 X-Emacs-PR-Package: emacs X-Emacs-PR-Keywords: Original-Received: via spool by 3746-submit@emacsbugs.donarmstrong.com id=B3746.125865293823693 (code B ref 3746); Thu, 19 Nov 2009 17:55:07 +0000 Original-Received: (at 3746) by emacsbugs.donarmstrong.com; 19 Nov 2009 17:48:58 +0000 X-Spam-Bayes: score:0.5 Bayes not run. spammytokens:Tokens not available. hammytokens:Tokens not available. Original-Received: from mx1.starman.ee (smtp-out3.starman.ee [85.253.0.5]) by rzlab.ucr.edu (8.14.3/8.14.3/Debian-5) with ESMTP id nAJHmu9L023689 for <3746@emacsbugs.donarmstrong.com>; Thu, 19 Nov 2009 09:48:57 -0800 X-Virus-Scanned: by Amavisd-New at mx1.starman.ee Original-Received: from mail.starman.ee (82.131.33.165.cable.starman.ee [82.131.33.165]) by mx1.starman.ee (Postfix) with ESMTP id 4D5E03F4133; Thu, 19 Nov 2009 19:48:50 +0200 (EET) In-Reply-To: <87ljmxo5pw.fsf@mail.jurta.org> (Juri Linkov's message of "Fri, 10 Jul 2009 01:19:11 +0300") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1.50 (x86_64-pc-linux-gnu) X-detected-operating-system: by monty-python.gnu.org: GNU/Linux 2.6 (newer, 2) Resent-Date: Thu, 19 Nov 2009 13:07:29 -0500 X-BeenThere: bug-gnu-emacs@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:32721 Archived-At: --=-=-= Please see the attached code that implements isearch in comint mode. It is not posted as a patch because it has one remaining problem: `comint-previous-input' and `comint-next-input' don't signal an error at the beginning/end of the history ring. This is unlike the minibuffer's commands `previous-history-element' and `next-history-element' that signal an error at the beginning/end of the minibuffer history. So Isearch on the minibuffer history can stop and wrap. But in comint mode Isearch with an unmatched string doesn't stop and goes into the loop. Maybe we should change `comint-previous-input' and `comint-next-input' to signal an error at the beginning/end of the history ring? --=-=-= Content-Type: application/emacs-lisp Content-Disposition: inline; filename=comint.history.isearch.el Content-Transfer-Encoding: quoted-printable ;; isearch input history (defcustom comint-history-isearch nil "Non-nil to Isearch in input history only, not in comint output. If t, Isearch in comint mode always matches only input history. If `dwim', Isearch matches input history when initial point position is at comint command line. If nil, it searches the whole comint buffer." :type '(choice (const :tag "Don't search in input history" nil) (const :tag "When point is on command line initially, search history" dw= im) (const :tag "Always search in input history" t)) :group 'comint :version "23.2") (defun comint-history-isearch-backward () "Search for a string backward in input history using Isearch." (interactive) (let ((comint-history-isearch t)) (isearch-backward))) ;; FIXME: This should be added to `comint-mode': (add-hook 'comint-mode-hook (lambda () (define-key comint-mode-map "\M-r" 'comint-history-isearch-backward) (add-hook 'isearch-mode-hook 'comint-history-isearch-setup nil t))) (defvar comint-history-isearch-message-overlay) (make-variable-buffer-local 'comint-history-isearch-message-overlay) (defun comint-history-isearch-setup () "Set up a comint for using isearch to search the input history. Intended to be added to `comint-mode-hook'." (when (or (eq comint-history-isearch t) (and (eq comint-history-isearch 'dwim) ;; Point is at command line. (comint-after-pmark-p))) (setq isearch-message-prefix-add "history ") (set (make-local-variable 'isearch-search-fun-function) 'comint-history-isearch-search) (set (make-local-variable 'isearch-message-function) 'comint-history-isearch-message) (set (make-local-variable 'isearch-wrap-function) 'comint-history-isearch-wrap) (set (make-local-variable 'isearch-push-state-function) 'comint-history-isearch-push-state) (add-hook 'isearch-mode-end-hook 'comint-history-isearch-end nil t))) (defun comint-history-isearch-end () "Clean up the comint after terminating isearch in the comint." (if comint-history-isearch-message-overlay (delete-overlay comint-history-isearch-message-overlay)) (setq isearch-message-prefix-add nil) (setq isearch-search-fun-function nil) (setq isearch-message-function nil) (setq isearch-wrap-function nil) (setq isearch-push-state-function nil) (remove-hook 'isearch-mode-end-hook 'comint-history-isearch-end t)) (defun comint-goto-input (pos) "Put input history of the absolute history position POS." ;; Logic from `comint-previous-matching-input'. ;; It should be like `goto-history-element'. (if (null comint-input-ring-index) (setq comint-stored-incomplete-input (funcall comint-get-old-input))) (setq comint-input-ring-index pos) (comint-delete-input) (when pos (insert (ring-ref comint-input-ring pos)))) (defun comint-history-isearch-search () "Return the proper search function, for isearch in input 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 comint 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 comint prompt when ;; searching forward. Lazy-highlight calls this lambda with the ;; bound arg, so skip the comint prompt. (if (and bound isearch-forward (< (point) (comint-line-beginning-position)= )) (goto-char (comint-line-beginning-position))) (or ;; 1. First try searching in the initial comint text (funcall search-fun string (if isearch-forward bound (comint-line-beginning-position)) noerror) ;; 2. If the above search fails, start putting next/prev history ;; elements in the comint 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 comint text). (unless bound (condition-case nil (progn (while (not found) (cond (isearch-forward (comint-next-input 1) (goto-char (comint-line-beginning-position))) (t (comint-previous-input 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 comint-next-input ;; or comint-previous-input 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 comint prompt (comint-line-beginning-position)) noerror))) ;; Return point of the new search result (point)) ;; Return nil when next(prev)-history-element fails (error nil))))))))) (defun comint-history-isearch-message (&optional c-q-hack ellipsis) "Display the input history search prompt. If there are no search errors, this function displays an overlay with the isearch prompt which replaces the original comint prompt. Otherwise, it displays the standard isearch message returned from `isearch-message'." (if (not (and isearch-success (not isearch-error))) ;; Use standard function `isearch-message' when not in the comint, ;; or search fails, or has an error (like incomplete regexp). ;; This function overwrites comint 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 comint prompt. (if (overlayp comint-history-isearch-message-overlay) (move-overlay comint-history-isearch-message-overlay (save-excursion (forward-line 0) (point)) (comint-line-beginning-position)) (setq comint-history-isearch-message-overlay (make-overlay (save-excursion (forward-line 0) (point)) (comint-line-beginning-position))) (overlay-put comint-history-isearch-message-overlay 'evaporate t)) (overlay-put comint-history-isearch-message-overlay 'display (isearch-message-prefix c-q-hack ellipsis)) ;; And clear any previous isearch message. (message ""))) (defun comint-history-isearch-wrap () "Wrap the input history search when search fails. 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 `comint-history-isearch-search' fails on reaching the ;; beginning/end of the history, wrap the search to the first/last ;; input history element. (if isearch-forward (comint-goto-input (length (symbol-value comint-history-variable))) (comint-goto-input nil)) (setq isearch-success t)) (goto-char (if isearch-forward (comint-line-beginning-position) (point-ma= x)))) (defun comint-history-isearch-push-state () "Save a function restoring the state of input history search. Save `comint-input-ring-index' to the additional state parameter in the search status stack." `(lambda (cmd) (comint-history-isearch-pop-state cmd ,comint-input-ring-index))) (defun comint-history-isearch-pop-state (cmd hist-pos) "Restore the input history search state. Go to the history element by the absolute history position HIST-POS." (comint-goto-input hist-pos)) --=-=-= -- Juri Linkov http://www.jurta.org/emacs/ --=-=-=--