emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A better UI than perform-replace


From: Dmitry Gutov
Subject: Re: A better UI than perform-replace
Date: Mon, 16 Nov 2015 20:01:00 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/20100101 Thunderbird/42.0

On 11/16/2015 01:47 PM, Oleh Krehel wrote:

I think a better UI for `perform-replace' is warranted.  The current
thing is very basic:

- No good way to see how many matches there are.
- No good way to get an overview of matches per buffer.
- No good way to pause the replacement procedure.
- No good way to undo a replacement.

Indeed.

An idea to improve this would be with a permanent *replace* buffer,
similar to `dired' or *Buffer List*. This buffer would be visible during
the replacement operation, together with the actual buffers that contain
the candidates. Here are some ideas for key bindings and the general
interface:

Maybe a universal "replace buffer" is the way to go. I'd expected to have an xref-specific replace buffer first, though.

Or even modify the existing xref buffer inline when you press `r', to add some widgets to signify marks (maybe just a couple of columns), you'd be able to select the lines you want to rename, perform the rename, and then maybe see the xref results refreshed, with only those hits that you haven't changes, remaining (maybe you want to do something else with them).

But don't let me stop you from working on a generic feature - after all, query-replace is used in many places.

0. The *replace* buffer would be organized in branches by buffer, just
like *xref* is currently.

1. "y" would mark the current item for replacement, which corresponds to
the current line in the *replace* buffer, and advance to the next line.

Or `m', which we use for marks, usually.

2. "n" would mark the current item for non-replacement, and advance to
the next line. This is to distinguish the items for which no decision
was made yet: they don't have a `y' or `n' mark.

I see the keystroke-saving benefits, but maybe we should start with the usual approach of p/n for up/down, and m/u to mark/unmark. `% m' to mark by regexp, `U' to unmark all, `t' to toggle all marks. Press `m' while cursor is on a group header -> and its marks all its elements, and similar for `u'.

3. "Y" would mark all items from the current one until the end of the
current buffer branch. "N" would work in a similar way.

4. "c" could change the replacement text for a single item. The mark
would change appropriately.

5. "C" could change the replacement text for all following items.

That might be cool to try, too.

6. "x" would execute all requested changes.

7. "e" would launch an `ediff' session to review the changes that "x"
would do.

Wouldn't hurt.

8. After "x", the *replace* buffer stays behind until the user kills it.
It should serve to review the changes. Possibly "u" could be used to
revert a performed change for the current item.

Sounds good.

9. "C-n", "C-p" and any other navigational commands should work as
usual. Except changing the current item in *replace* should result in
that item being displayed in its native buffer - exactly what "C-o"
currently does in *xref*.

That description seems incomplete. Either we shouldn't mess with what's displayed in other buffers (and maybe implement a direct counterpart to "C-o"), or the *replace* buffer should always display the current item in the "other window". But I'm inclined toward the former.

As another alternative, we could should a few lines of context for the current match inside the *replace* buffer, if the user asks (e.g. with `+' increasing the context height, and `-' reducing it).

To re-describe things in a shorter way, *replace* should be a staging
area for the `perform-replace' operation. With the ability to quickly
view and manipulate the separate replacements, the ability to defer it
indefinitely, and the ability to finalize the operation with "x".

With the ability to "defer it", there'll also come a need to check whether the inputs (search matches?) are up-to-date. That puts some restrictions on what it can work with.

I post this idea here for feedback. Maybe there's a better way to do
this. Maybe there are ideas to further improve my *replace* proposal.

Another thing I haven't seen mentioned in this list, is the ability to rename a file, as a part of search-replace. It may not be needed if one performs a textual search, but for the "rename" refactoring operation, if I rename a class in Ruby or Java, I want to have its file to be renamed automatically as well.

So ideally, the replace buffer would allow to preview that operation as well. I'm still thinking how to better support that in xref data structures.

> Maybe there's a wish to have this functionality in the core.

Where else?



reply via email to

[Prev in Thread] Current Thread [Next in Thread]