From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Dmitry Gutov Newsgroups: gmane.emacs.devel Subject: Re: A better UI than perform-replace Date: Mon, 16 Nov 2015 20:01:00 +0200 Message-ID: <564A19DC.5050707@yandex.ru> References: <56480D6C.2080408@yandex.ru> <876112xj2i.fsf@gmail.com> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=windows-1252; format=flowed Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1447716978 20731 80.91.229.3 (16 Nov 2015 23:36:18 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 16 Nov 2015 23:36:18 +0000 (UTC) Cc: emacs-devel To: Oleh Krehel Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Tue Nov 17 00:36:14 2015 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1ZyTJl-0007am-QL for ged-emacs-devel@m.gmane.org; Tue, 17 Nov 2015 00:36:14 +0100 Original-Received: from localhost ([::1]:51992 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZyTJl-0006jM-6h for ged-emacs-devel@m.gmane.org; Mon, 16 Nov 2015 18:36:13 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:35809) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZyO5Z-0002Qh-UA for emacs-devel@gnu.org; Mon, 16 Nov 2015 13:01:18 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZyO5Q-0008JT-PD for emacs-devel@gnu.org; Mon, 16 Nov 2015 13:01:13 -0500 Original-Received: from mail-wm0-x231.google.com ([2a00:1450:400c:c09::231]:33951) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZyO5Q-0008JN-FE for emacs-devel@gnu.org; Mon, 16 Nov 2015 13:01:04 -0500 Original-Received: by wmvv187 with SMTP id v187so189735832wmv.1 for ; Mon, 16 Nov 2015 10:01:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:subject:to:references:cc:from:message-id:date:user-agent :mime-version:in-reply-to:content-type:content-transfer-encoding; bh=8wzVkZ8yLbBdx9yMJovVLzhbJ6+BP+Fn203cetAV5AE=; b=tC6nhsVLXOaD0amAkU09g+4DxjF/Sr9aWdj4I8dvOTmBJNpBnFrVFwKvpbgAt8pQXc dPMRPPxbpNuq6y6YDo7Cp8uGKDmDg2ZzHgw75hCJDg7/NxMCBxtSiBQp8uw3HSwlCqO8 937Jh5NzNiMtfZYKH3rh0BqxLjaVJ71i/+0Yt8HaQlc/BXlIecPJ+St1Nu13E1TSZ2rO ENU4CJk/Plam5ef4qttTJ0KatWLpydCLSjpL1eLtzq3vSX4E0gjkmVvPuMEVEs4ni9g9 r8f7CjT8n6prhroVUY56Fi0pC4n3S6RWmAPAOwn+UftU/v6lDmPQdAZYHQTVj4LZchrr ytuw== X-Received: by 10.194.57.178 with SMTP id j18mr18321658wjq.113.1447696863765; Mon, 16 Nov 2015 10:01:03 -0800 (PST) Original-Received: from [10.9.0.103] (nat.webazilla.com. [78.140.128.228]) by smtp.googlemail.com with ESMTPSA id m135sm25025338wmb.0.2015.11.16.10.01.01 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 16 Nov 2015 10:01:02 -0800 (PST) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/20100101 Thunderbird/42.0 In-Reply-To: <876112xj2i.fsf@gmail.com> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a00:1450:400c:c09::231 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:194585 Archived-At: 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?