unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Doing search and replace via *grep* buffer
@ 2007-02-15 12:11 Kim F. Storm
  2007-02-15 12:35 ` Lennart Borgman (gmail)
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Kim F. Storm @ 2007-02-15 12:11 UTC (permalink / raw)
  To: emacs-devel


Here is a small patch which provides a very handy search and replace
functionality via the normal grep interfaces (including lgrep/rgrep).

It requires that grep regexp highlighting works (I suppose most modern
grep programs do that).


Here is an example of its use, replacing _some_ occurrences of 
the identifier `oldtext' with `newtext':

First use rgrep to search for oldtext in all .c and .h files:
  M-x rgrep RET oldtext RET ch RET RET

Then in the *grep* buffer, move to the first instance which you want to
replace (use `n' or C-n).

Then hit / and type the replacement text:
  / newtext RET

Now, still in the *grep* buffer, move to the next instance you want
to modify, and just hit . to repeat the replacement, for example:
  n n . n . n . n n n .

(I suppose VI users will find this very familiar).


*** grep.el	14 Feb 2007 12:54:20 +0100	1.69
--- grep.el	15 Feb 2007 12:46:01 +0100	
***************
*** 185,192 ****
--- 185,195 ----
      (define-key map "\r" 'compile-goto-error)  ;; ?
      (define-key map "n" 'next-error-no-select)
      (define-key map "p" 'previous-error-no-select)
+     (define-key map "o" 'grep-goto-error-no-select)
      (define-key map "{" 'compilation-previous-file)
      (define-key map "}" 'compilation-next-file)
+     (define-key map "/" 'grep-replace-match)
+     (define-key map "." 'grep-repeat-replace-match)
      (define-key map "\t" 'compilation-next-error)
      (define-key map [backtab] 'compilation-previous-error)
  
***************
*** 790,795 ****
--- 793,831 ----
  	  (if (eq next-error-last-buffer (current-buffer))
  	      (setq default-directory dir)))))))
  
+ (defun grep-goto-error-no-select ()
+   "Display currently grep match in other window."
+   (interactive)
+   (save-selected-window
+     (compile-goto-error)))
+ 
+ (defvar grep-last-replace-string nil)
+ 
+ (defun grep-replace-match-internal ()
+   (when compilation-highlight-overlay
+     (let ((start (overlay-start compilation-highlight-overlay)))
+       (goto-char start)
+       (undo-boundary)
+       (delete-region start (overlay-end compilation-highlight-overlay))
+       (insert grep-last-replace-string)
+       (move-overlay compilation-highlight-overlay start (point)))))
+ 
+ (defun grep-replace-match (string)
+   "Replace current grep match with string STRING."
+   (interactive "sReplace with: ")
+   (save-selected-window
+     (setq grep-last-replace-string string)
+     (let ((next-error-highlight
+ 	   (if (numberp next-error-highlight) next-error-highlight 0.01))
+ 	  (next-error-hook '(grep-replace-match-internal)))
+       (compile-goto-error))))
+ 
+ (defun grep-repeat-replace-match ()
+   "Replace current grep match with last match replace string."
+   (interactive)
+   (if (not grep-last-replace-string)
+       (call-interactively 'grep-replace-match)
+     (grep-replace-match grep-last-replace-string)))
+ 
  
  (provide 'grep)
  

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doing search and replace via *grep* buffer
  2007-02-15 12:11 Kim F. Storm
@ 2007-02-15 12:35 ` Lennart Borgman (gmail)
  2007-02-15 13:46   ` Kim F. Storm
  2007-02-15 14:04 ` Chris Moore
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Lennart Borgman (gmail) @ 2007-02-15 12:35 UTC (permalink / raw)
  To: Kim F. Storm; +Cc: emacs-devel

Kim F. Storm wrote:
> Here is a small patch which provides a very handy search and replace
> functionality via the normal grep interfaces (including lgrep/rgrep).
> 
> It requires that grep regexp highlighting works (I suppose most modern
> grep programs do that).
> 
> 
> Here is an example of its use, replacing _some_ occurrences of 
> the identifier `oldtext' with `newtext':
> 
> First use rgrep to search for oldtext in all .c and .h files:
>   M-x rgrep RET oldtext RET ch RET RET
> 
> Then in the *grep* buffer, move to the first instance which you want to
> replace (use `n' or C-n).
> 
> Then hit / and type the replacement text:
>   / newtext RET
> 
> Now, still in the *grep* buffer, move to the next instance you want
> to modify, and just hit . to repeat the replacement, for example:
>   n n . n . n . n n n .
> 
> (I suppose VI users will find this very familiar).


Looks very interesting, but would it not be possible to use a prompting 
similar for other replace commands in Emacs?

(From a Viper user.)

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doing search and replace via *grep* buffer
  2007-02-15 12:35 ` Lennart Borgman (gmail)
@ 2007-02-15 13:46   ` Kim F. Storm
  2007-02-15 14:16     ` Lennart Borgman (gmail)
  2007-02-15 16:47     ` Stefan Monnier
  0 siblings, 2 replies; 13+ messages in thread
From: Kim F. Storm @ 2007-02-15 13:46 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: emacs-devel

"Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:

> Looks very interesting, but would it not be possible to use a
> prompting similar for other replace commands in Emacs?

I don't follow...  Example, please.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doing search and replace via *grep* buffer
  2007-02-15 12:11 Kim F. Storm
  2007-02-15 12:35 ` Lennart Borgman (gmail)
@ 2007-02-15 14:04 ` Chris Moore
  2007-02-16  8:51   ` David Kastrup
  2007-02-15 18:41 ` Andreas Roehler
  2007-02-16  7:46 ` Richard Stallman
  3 siblings, 1 reply; 13+ messages in thread
From: Chris Moore @ 2007-02-15 14:04 UTC (permalink / raw)
  To: Kim F. Storm; +Cc: emacs-devel

On 2/15/07, Kim F. Storm <storm@cua.dk> wrote:

> Then hit / and type the replacement text:
>   / newtext RET
>
> Now, still in the *grep* buffer, move to the next instance you want
> to modify, and just hit . to repeat the replacement, for example:
>   n n . n . n . n n n .
>
> (I suppose VI users will find this very familiar).

vi users are used to / being used to search, not to replace.  and 'N'
is the key for 'previous match', not 'p'.  The interface you offer
here is similar enough to how things work in vi to confuse people.
Also, while using 'n' and 'p' to go up and down, there's no finger
available to press '.'; some other choice of key would be better.

How about 'r' to prompt for replacement text and do a replacement, and
'g' to do it a(g)ain on a different line?  The left hand easily
reaches 'r' and 'g' while the right hand is touching 'n' and 'p'.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doing search and replace via *grep* buffer
  2007-02-15 13:46   ` Kim F. Storm
@ 2007-02-15 14:16     ` Lennart Borgman (gmail)
  2007-02-15 19:39       ` David Kastrup
  2007-02-15 16:47     ` Stefan Monnier
  1 sibling, 1 reply; 13+ messages in thread
From: Lennart Borgman (gmail) @ 2007-02-15 14:16 UTC (permalink / raw)
  To: Kim F. Storm; +Cc: emacs-devel

Kim F. Storm wrote:
> "Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:
> 
>> Looks very interesting, but would it not be possible to use a
>> prompting similar for other replace commands in Emacs?
> 
> I don't follow...  Example, please.


There are some replace entries in the menus, for example: Edit - Replace 
- Replace Regexp. That entry prompt first for a regexp to match (not 
applicable here) and then for the action to take. I meant something 
similar to the action prompt.

And it would be nice with an entry there in the edit menu when you are 
in the grep buffer.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doing search and replace via *grep* buffer
  2007-02-15 13:46   ` Kim F. Storm
  2007-02-15 14:16     ` Lennart Borgman (gmail)
@ 2007-02-15 16:47     ` Stefan Monnier
  1 sibling, 0 replies; 13+ messages in thread
From: Stefan Monnier @ 2007-02-15 16:47 UTC (permalink / raw)
  To: Kim F. Storm; +Cc: Lennart Borgman (gmail), emacs-devel

>> Looks very interesting, but would it not be possible to use a
>> prompting similar for other replace commands in Emacs?

> I don't follow...  Example, please.

To me The Right Way to do it is to change query-replace so that it uses
a "perform-replace-function" variable which could be used to hook into the
replacement and to reflect it ni the source buffers.


        Stefan

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doing search and replace via *grep* buffer
  2007-02-15 12:11 Kim F. Storm
  2007-02-15 12:35 ` Lennart Borgman (gmail)
  2007-02-15 14:04 ` Chris Moore
@ 2007-02-15 18:41 ` Andreas Roehler
  2007-02-16  7:46 ` Richard Stallman
  3 siblings, 0 replies; 13+ messages in thread
From: Andreas Roehler @ 2007-02-15 18:41 UTC (permalink / raw)
  To: Kim F. Storm; +Cc: emacs-devel


Thanks, already looked for something like that.

`grep-replace-match' changes original contents as
expected if cursor in grep-buffer is over match
(highlighted).

Otherwise I'm still prompted for replacement, but get

"compilation-next-error: No grep hit here"

afterwards.

__
Andreas Roehler

GNU Emacs 22.0.93.1 (i686-pc-linux-gnu, X toolkit,
Xaw3d scroll bars) of 2007-02-11

Suse 10.0




Kim F. Storm schrieb:
> Here is a small patch which provides a very handy search and replace
> functionality via the normal grep interfaces (including lgrep/rgrep).
>
> It requires that grep regexp highlighting works (I suppose most modern
> grep programs do that).
>
>
> Here is an example of its use, replacing _some_ occurrences of 
> the identifier `oldtext' with `newtext':
>
> First use rgrep to search for oldtext in all .c and .h files:
>   M-x rgrep RET oldtext RET ch RET RET
>
> Then in the *grep* buffer, move to the first instance which you want to
> replace (use `n' or C-n).
>
> Then hit / and type the replacement text:
>   / newtext RET
>
> Now, still in the *grep* buffer, move to the next instance you want
> to modify, and just hit . to repeat the replacement, for example:
>   n n . n . n . n n n .
>
> (I suppose VI users will find this very familiar).
>
>
> *** grep.el	14 Feb 2007 12:54:20 +0100	1.69
> --- grep.el	15 Feb 2007 12:46:01 +0100	
> ***************
> *** 185,192 ****
> --- 185,195 ----
>       (define-key map "\r" 'compile-goto-error)  ;; ?
>       (define-key map "n" 'next-error-no-select)
>       (define-key map "p" 'previous-error-no-select)
> +     (define-key map "o" 'grep-goto-error-no-select)
>       (define-key map "{" 'compilation-previous-file)
>       (define-key map "}" 'compilation-next-file)
> +     (define-key map "/" 'grep-replace-match)
> +     (define-key map "." 'grep-repeat-replace-match)
>       (define-key map "\t" 'compilation-next-error)
>       (define-key map [backtab] 'compilation-previous-error)
>   
> ***************
> *** 790,795 ****
> --- 793,831 ----
>   	  (if (eq next-error-last-buffer (current-buffer))
>   	      (setq default-directory dir)))))))
>   
> + (defun grep-goto-error-no-select ()
> +   "Display currently grep match in other window."
> +   (interactive)
> +   (save-selected-window
> +     (compile-goto-error)))
> + 
> + (defvar grep-last-replace-string nil)
> + 
> + (defun grep-replace-match-internal ()
> +   (when compilation-highlight-overlay
> +     (let ((start (overlay-start compilation-highlight-overlay)))
> +       (goto-char start)
> +       (undo-boundary)
> +       (delete-region start (overlay-end compilation-highlight-overlay))
> +       (insert grep-last-replace-string)
> +       (move-overlay compilation-highlight-overlay start (point)))))
> + 
> + (defun grep-replace-match (string)
> +   "Replace current grep match with string STRING."
> +   (interactive "sReplace with: ")
> +   (save-selected-window
> +     (setq grep-last-replace-string string)
> +     (let ((next-error-highlight
> + 	   (if (numberp next-error-highlight) next-error-highlight 0.01))
> + 	  (next-error-hook '(grep-replace-match-internal)))
> +       (compile-goto-error))))
> + 
> + (defun grep-repeat-replace-match ()
> +   "Replace current grep match with last match replace string."
> +   (interactive)
> +   (if (not grep-last-replace-string)
> +       (call-interactively 'grep-replace-match)
> +     (grep-replace-match grep-last-replace-string)))
> + 
>   
>   (provide 'grep)
>   
>
>   

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doing search and replace via *grep* buffer
  2007-02-15 14:16     ` Lennart Borgman (gmail)
@ 2007-02-15 19:39       ` David Kastrup
  0 siblings, 0 replies; 13+ messages in thread
From: David Kastrup @ 2007-02-15 19:39 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: emacs-devel, Kim F. Storm

"Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:

> Kim F. Storm wrote:
>> "Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:
>>
>>> Looks very interesting, but would it not be possible to use a
>>> prompting similar for other replace commands in Emacs?
>>
>> I don't follow...  Example, please.
>
>
> There are some replace entries in the menus, for example: Edit -
> Replace - Replace Regexp. That entry prompt first for a regexp to
> match (not applicable here) and then for the action to take. I meant
> something similar to the action prompt.
>
> And it would be nice with an entry there in the edit menu when you are
> in the grep buffer.

I find all of this far too contrived.  We don't need a bunch of new
keybindings and stuff.

Instead, if such functionality is desired, one can just make a minor
mode that will make C-x C-s save all changes in the grep buffer to the
respective files (for efficiency reasons, this might imply going
through the undo stack and getting the info about affected files and
lines, or after-modification-hook keeps track of the changes required
to the files in question).

That means that normal search and replace can be used on the buffer.
One just has to make sure that changes to file name and line number in
the buffer are flagged as an error (perhaps it is easiest to make them
read-only already when they are placed into the buffer).

-- 
David Kastrup, Kriemhildstr. 15, 44793 Bochum

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doing search and replace via *grep* buffer
  2007-02-15 12:11 Kim F. Storm
                   ` (2 preceding siblings ...)
  2007-02-15 18:41 ` Andreas Roehler
@ 2007-02-16  7:46 ` Richard Stallman
  3 siblings, 0 replies; 13+ messages in thread
From: Richard Stallman @ 2007-02-16  7:46 UTC (permalink / raw)
  To: Kim F. Storm; +Cc: emacs-devel

Please save such suggestions for after the release.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doing search and replace via *grep* buffer
  2007-02-15 14:04 ` Chris Moore
@ 2007-02-16  8:51   ` David Kastrup
  0 siblings, 0 replies; 13+ messages in thread
From: David Kastrup @ 2007-02-16  8:51 UTC (permalink / raw)
  To: Chris Moore; +Cc: emacs-devel, Kim F. Storm

"Chris Moore" <christopher.ian.moore@gmail.com> writes:

> On 2/15/07, Kim F. Storm <storm@cua.dk> wrote:
>
>> Then hit / and type the replacement text:
>>   / newtext RET
>>
>> Now, still in the *grep* buffer, move to the next instance you want
>> to modify, and just hit . to repeat the replacement, for example:
>>   n n . n . n . n n n .
>>
>> (I suppose VI users will find this very familiar).
>
> vi users are used to / being used to search, not to replace.  and 'N'
> is the key for 'previous match', not 'p'.  The interface you offer
> here is similar enough to how things work in vi to confuse people.
> Also, while using 'n' and 'p' to go up and down, there's no finger
> available to press '.'; some other choice of key would be better.
>
> How about 'r' to prompt for replacement text and do a replacement, and
> 'g' to do it a(g)ain on a different line?  The left hand easily
> reaches 'r' and 'g' while the right hand is touching 'n' and 'p'.

We don't want to design new keybindings.  I explained previously how
to do this in a manner that does not require the user to learn
completely new keybindings.

And anyway, Richard already said to save this discussion for after the
release.

-- 
David Kastrup

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Doing search and replace via *grep* buffer
@ 2007-10-11 15:17 René Kyllingstad
  2007-10-11 16:12 ` Drew Adams
  2007-10-12  2:46 ` Richard Stallman
  0 siblings, 2 replies; 13+ messages in thread
From: René Kyllingstad @ 2007-10-11 15:17 UTC (permalink / raw)
  To: emacs-devel

Hi,

in February Kim posted a patch to allow doing search and replace via the
*grep* buffer.  I think that would be a great feature to have inluded in
Emacs.  David and Stefan suggested other ways of implementing same, but
there was the pending release to focus on.

Anyone in the mood for it now?  It would be sweet. 



-- René
http://lists.gnu.org/archive/html/emacs-devel/2007-02/msg00683.html

^ permalink raw reply	[flat|nested] 13+ messages in thread

* RE: Doing search and replace via *grep* buffer
  2007-10-11 15:17 Doing search and replace via *grep* buffer René Kyllingstad
@ 2007-10-11 16:12 ` Drew Adams
  2007-10-12  2:46 ` Richard Stallman
  1 sibling, 0 replies; 13+ messages in thread
From: Drew Adams @ 2007-10-11 16:12 UTC (permalink / raw)
  To: René Kyllingstad, emacs-devel

> in February Kim posted a patch to allow doing search and replace via the
> *grep* buffer.  I think that would be a great feature to have inluded in
> Emacs.  David and Stefan suggested other ways of implementing same, but
> there was the pending release to focus on.
>
> Anyone in the mood for it now?  It would be sweet.

See also the thread "be able to replace during isearch" at the beginning of
July 2007. The idea is to replace particular search hits on demand, during
isearch. This is quite different from a query-replace approach, where you
are asked about each hit. You just hit a key if you want to replace the
current hit. A different key would let you redefine the replacement string.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Doing search and replace via *grep* buffer
  2007-10-11 15:17 Doing search and replace via *grep* buffer René Kyllingstad
  2007-10-11 16:12 ` Drew Adams
@ 2007-10-12  2:46 ` Richard Stallman
  1 sibling, 0 replies; 13+ messages in thread
From: Richard Stallman @ 2007-10-12  2:46 UTC (permalink / raw)
  To: René Kyllingstad; +Cc: kfs, emacs-devel

The feature looks useful, but I wonder why it is implemented using
next-error-hook.  If this it can be done in a more natural way, let's
rewrite it more naturally.  Or, if there is a reason that this is the
right way, let's put in comments explaining why that is so.

Also, all the functions and variables should have doc strings to explain
how they are used.

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2007-10-12  2:46 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-10-11 15:17 Doing search and replace via *grep* buffer René Kyllingstad
2007-10-11 16:12 ` Drew Adams
2007-10-12  2:46 ` Richard Stallman
  -- strict thread matches above, loose matches on Subject: below --
2007-02-15 12:11 Kim F. Storm
2007-02-15 12:35 ` Lennart Borgman (gmail)
2007-02-15 13:46   ` Kim F. Storm
2007-02-15 14:16     ` Lennart Borgman (gmail)
2007-02-15 19:39       ` David Kastrup
2007-02-15 16:47     ` Stefan Monnier
2007-02-15 14:04 ` Chris Moore
2007-02-16  8:51   ` David Kastrup
2007-02-15 18:41 ` Andreas Roehler
2007-02-16  7:46 ` 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).