🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.emacs.bug
Article #87706

incremental query-replace

#87706
From: Tom Tromey
Date: Fri, 02 Sep 1994 21:55
294 lines
12438 bytes
Appended are some patches that allow query-replace to search for the
replacement string (or regexp) using isearch.  I've found that I often
bungle complicated regexps with query-replace-regexp.  This patch
makes it much easier to see what is going to happen before you commit.

Included are a couple small patches to isearch to implement
functionality I needed.

Those in the viewing audience: these patches will not work without
some other isearch patches that RMS sent me.  If you really want
query-replace to work interactively, send me mail and I will send the
other isearch patches.

To get interactive behavior, set query-replace-incremental to any
non-nil value.  Currently the default is nil because history does not
work right.  I think the best way to make history work would be to
make isearch use ring.el's rings (currently it uses its own).  I have
not done this.

Here is a ChangeLog entry:

Tue Aug 30 12:12:41 1994  Tom Tromey  (tromey@drip.colorado.edu)

	* isearch.el (isearch-abort): Abort means bad exit.
	(isearch-override-name): New variable.
	(isearch-message-prefix): Use it.

	* replace.el (query-replace-read-args): Rewritten to deal with
	incremental searches.  Changed all callers.

Tom
---
tromey@busco.lanl.gov             Member, League for Programming Freedom
((lambda (lambda) `(,lambda ',lambda)) '(lambda (lambda) `(,lambda ',lambda)))

*** ../lisp/isearch.el	Sat May 14 03:50:30 1994
--- isearch.el	Tue Aug 30 12:31:22 1994
***************
*** 59,69 ****
  ;; keep the behavior.  No point in forcing nonincremental search until
  ;; the last possible moment.
  
  ;; TODO
  ;; - Integrate the emacs 19 generalized command history.
- ;; - Think about incorporating query-replace.
  ;; - Hooks and options for failed search.
  
  ;;; Change Log:
  
  ;;; Changes before those recorded in ChangeLog:
--- 59,68 ----
***************
*** 368,377 ****
--- 367,379 ----
  (defvar isearch-nonincremental nil)
  
  ;; New value of isearch-forward after isearch-edit-string.
  (defvar isearch-new-forward nil)
  
+ ;; String to display instead of "I-search".
+ (defvar isearch-override-name nil)
+ 
  
  ;;;==============================================================
  ;; Minor-mode-alist changes - kind of redundant with the
  ;; echo area, but if isearching in multiple windows, it can be useful.
  
***************
*** 809,820 ****
    (discard-input)
    (if isearch-success
        ;; If search is successful, move back to starting point
        ;; and really do quit.
        (progn (goto-char isearch-opoint)
! 	     (isearch-done t)   ; exit isearch
! 	     (signal 'quit nil))  ; and pass on quit signal
      ;; If search is failing, rub out until it is once more successful.
      (while (not isearch-success) (isearch-pop-state))
      (isearch-update)))
  
  
--- 811,823 ----
    (discard-input)
    (if isearch-success
        ;; If search is successful, move back to starting point
        ;; and really do quit.
        (progn (goto-char isearch-opoint)
! 	     (setq isearch-success nil)	; bad exit from isearch
! 	     (isearch-done t)		; exit isearch
! 	     (signal 'quit nil))	; and pass on quit signal
      ;; If search is failing, rub out until it is once more successful.
      (while (not isearch-success) (isearch-pop-state))
      (isearch-update)))
  
  
***************
*** 1301,1311 ****
    (or isearch-success (setq ellipsis nil))
    (let ((m (concat (if isearch-success "" "failing ")
  		   (if isearch-wrapped "wrapped ")
  		   (if isearch-word "word " "")
  		   (if isearch-regexp "regexp " "")
! 		   (if nonincremental "search" "I-search")
  		   (if isearch-forward ": " " backward: ")
  		   )))
      (aset m 0 (upcase (aref m 0)))
      m))
  
--- 1304,1316 ----
    (or isearch-success (setq ellipsis nil))
    (let ((m (concat (if isearch-success "" "failing ")
  		   (if isearch-wrapped "wrapped ")
  		   (if isearch-word "word " "")
  		   (if isearch-regexp "regexp " "")
! 		   (if nonincremental
! 		       "search"
! 		     (or isearch-override-name "I-search"))
  		   (if isearch-forward ": " " backward: ")
  		   )))
      (aset m 0 (upcase (aref m 0)))
      m))
  

*** ../lisp/replace.el	Sun May  1 16:55:36 1994
--- replace.el	Tue Aug 30 12:31:16 1994
***************
*** 26,46 ****
  ;;; Code:
  
  (defconst case-replace t "\
  *Non-nil means query-replace should preserve case in replacements.")
  
  (defvar query-replace-history nil)
  
! (defun query-replace-read-args (string)
    (let (from to)
!     (setq from (read-from-minibuffer (format "%s: " string)
! 				     nil nil nil
! 				     'query-replace-history))
!     (setq to (read-from-minibuffer (format "%s %s with: " string from)
  				   nil nil nil
  				   'query-replace-history))
!     (list from to current-prefix-arg)))
  
  (defun query-replace (from-string to-string &optional arg)
    "Replace some occurrences of FROM-STRING with TO-STRING.
  As each match is found, the user must type a character saying
  what to do with it.  For directions, type \\[help-command] at that time.
--- 26,67 ----
  ;;; Code:
  
  (defconst case-replace t "\
  *Non-nil means query-replace should preserve case in replacements.")
  
+ (defvar query-replace-incremental nil
+   "*If not nil, query-replace and friends do incremental searches.")
+ 
  (defvar query-replace-history nil)
  
! 
! ;; Read args for query-replace.  PROMPT is the prompt.  If not nil,
! ;; REGEXP means do regexp search.  DELIMITED means search is for exact
! ;; words only.
! (defun query-replace-read-args (prompt regexp delimited)
    (let (from to)
!     ;; FIXME should push history onto query-replace history in
!     ;; incremental case.  How?
!     (if query-replace-incremental
! 	(let ((isearch-override-name prompt)
! 	      (search-nonincremental-instead nil)
! 	      (isearch-word delimited))
! 	  (save-excursion
! 	    (if regexp
! 		(isearch-forward-regexp)
! 	      (isearch-forward)))
! 	  ;; Not sure what do to on bad isearch.  So we just punt.
! 	  (or isearch-success
! 	      (signal 'quit nil))
! 	  (setq from isearch-string))
!       (setq from (read-from-minibuffer (format "%s: " prompt)
! 				       nil nil nil
! 				       'query-replace-history)))
!     (setq to (read-from-minibuffer (format "%s %s with: " prompt from)
  				   nil nil nil
  				   'query-replace-history))
!     (list from to delimited)))
  
  (defun query-replace (from-string to-string &optional arg)
    "Replace some occurrences of FROM-STRING with TO-STRING.
  As each match is found, the user must type a character saying
  what to do with it.  For directions, type \\[help-command] at that time.
***************
*** 49,59 ****
  are non-nil and FROM-STRING has no uppercase letters.
  Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
  only matches surrounded by word boundaries.
  
  To customize possible responses, change the \"bindings\" in `query-replace-map'."
!   (interactive (query-replace-read-args "Query replace"))
    (perform-replace from-string to-string t nil arg)
    (or unread-command-events (message "Done")))
  (define-key esc-map "%" 'query-replace)
  
  (defun query-replace-regexp (regexp to-string &optional arg)
--- 70,81 ----
  are non-nil and FROM-STRING has no uppercase letters.
  Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
  only matches surrounded by word boundaries.
  
  To customize possible responses, change the \"bindings\" in `query-replace-map'."
!   (interactive
!    (query-replace-read-args "Query replace" nil current-prefix-arg))
    (perform-replace from-string to-string t nil arg)
    (or unread-command-events (message "Done")))
  (define-key esc-map "%" 'query-replace)
  
  (defun query-replace-regexp (regexp to-string &optional arg)
***************
*** 66,76 ****
  Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
  only matches surrounded by word boundaries.
  In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP,
  and `\\=\\N' (where N is a digit) stands for
   whatever what matched the Nth `\\(...\\)' in REGEXP."
!   (interactive (query-replace-read-args "Query replace regexp"))
    (perform-replace regexp to-string t t arg)
    (or unread-command-events (message "Done")))
  
  (defun map-query-replace-regexp (regexp to-strings &optional arg)
    "Replace some matches for REGEXP with various strings, in rotation.
--- 88,99 ----
  Third arg DELIMITED (prefix arg if interactive), if non-nil, means replace
  only matches surrounded by word boundaries.
  In TO-STRING, `\\&' stands for whatever matched the whole of REGEXP,
  and `\\=\\N' (where N is a digit) stands for
   whatever what matched the Nth `\\(...\\)' in REGEXP."
!   (interactive
!    (query-replace-read-args "Query replace regexp" t current-prefix-arg))
    (perform-replace regexp to-string t t arg)
    (or unread-command-events (message "Done")))
  
  (defun map-query-replace-regexp (regexp to-strings &optional arg)
    "Replace some matches for REGEXP with various strings, in rotation.
***************
*** 120,130 ****
  This function is usually the wrong thing to use in a Lisp program.
  What you probably want is a loop like this:
    (while (search-forward FROM-STRING nil t)
      (replace-match TO-STRING nil t))
  which will run faster and will not set the mark or print anything."
!   (interactive (query-replace-read-args "Replace string"))
    (perform-replace from-string to-string nil nil delimited)
    (or unread-command-events (message "Done")))
  
  (defun replace-regexp (regexp to-string &optional delimited)
    "Replace things after point matching REGEXP with TO-STRING.
--- 143,154 ----
  This function is usually the wrong thing to use in a Lisp program.
  What you probably want is a loop like this:
    (while (search-forward FROM-STRING nil t)
      (replace-match TO-STRING nil t))
  which will run faster and will not set the mark or print anything."
!   (interactive
!    (query-replace-read-args "Replace string" nil current-prefix-arg))
    (perform-replace from-string to-string nil nil delimited)
    (or unread-command-events (message "Done")))
  
  (defun replace-regexp (regexp to-string &optional delimited)
    "Replace things after point matching REGEXP with TO-STRING.
***************
*** 139,149 ****
  This function is usually the wrong thing to use in a Lisp program.
  What you probably want is a loop like this:
    (while (re-search-forward REGEXP nil t)
      (replace-match TO-STRING nil nil))
  which will run faster and will not set the mark or print anything."
!   (interactive (query-replace-read-args "Replace regexp"))
    (perform-replace regexp to-string nil t delimited)
    (or unread-command-events (message "Done")))
  
  (defvar regexp-history nil
    "History list for some commands that read regular expressions.")
--- 163,173 ----
  This function is usually the wrong thing to use in a Lisp program.
  What you probably want is a loop like this:
    (while (re-search-forward REGEXP nil t)
      (replace-match TO-STRING nil nil))
  which will run faster and will not set the mark or print anything."
!   (interactive (query-replace-read-args "Replace regexp" t current-prefix-arg))
    (perform-replace regexp to-string nil t delimited)
    (or unread-command-events (message "Done")))
  
  (defvar regexp-history nil
    "History list for some commands that read regular expressions.")
Technical Details
Message-ID: <9409022153.AA11089@busco.lanl.gov>
Path: arc1-ca.pugleaf.net!bga.com!news.sprintlink.net!redstone.interpath.net!ddsw1!panix!MathWorks.Com!europa.eng.gtefsd.com!howland.reston.ans.net!math.ohio-state.edu!pacific.mps.ohio-state.edu!cis.ohio-state.edu!busco.lanl.gov!tromey

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: fb2f1,30e155c4cb7db265,start
X-Google-Attributes: gidfb2f1,public
X-Google-ArrivalTime: 1994-09-02 17:08:43 PST
Path: arc1-ca.pugleaf.net!bga.com!news.sprintlink.net!redstone.interpath.net!ddsw1!panix!MathWorks.Com!europa.eng.gtefsd.com!howland.reston.ans.net!math.ohio-state.edu!pacific.mps.ohio-state.edu!cis.ohio-state.edu!busco.lanl.gov!tromey
From: tromey@busco.lanl.gov (Tom Tromey)
Newsgroups: gnu.emacs.bug
Subject: incremental query-replace
Date: 2 Sep 1994 17:55:56 -0400
Organization: GNUs Not Usenet
Lines: 294
Sender: daemon@cis.ohio-state.edu
Approved: bug-gnu-emacs@prep.ai.mit.edu
Distribution: gnu
Message-ID: <9409022153.AA11089@busco.lanl.gov>