Article View: gnu.emacs.bug
Article #87706incremental query-replace
From: Tom Tromey
Date: Fri, 02 Sep 1994 21:55
Date: Fri, 02 Sep 1994 21:55
294 lines
12438 bytes
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!tromeyShow 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>