From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: "Drew Adams" Newsgroups: gmane.emacs.devel Subject: RE: propose adding Icicles to Emacs Date: Thu, 14 Jun 2007 18:01:20 -0700 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset="iso-8859-15" Content-Transfer-Encoding: 7bit X-Trace: sea.gmane.org 1181869411 12700 80.91.229.12 (15 Jun 2007 01:03:31 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Fri, 15 Jun 2007 01:03:31 +0000 (UTC) Cc: emacs-devel@gnu.org To: Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Fri Jun 15 03:03:28 2007 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.50) id 1Hz0Dm-0003p6-6P for ged-emacs-devel@m.gmane.org; Fri, 15 Jun 2007 03:03:27 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Hz0Dl-0005f4-I7 for ged-emacs-devel@m.gmane.org; Thu, 14 Jun 2007 21:03:25 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Hz0Di-0005ez-SJ for emacs-devel@gnu.org; Thu, 14 Jun 2007 21:03:22 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Hz0Dh-0005en-1Z for emacs-devel@gnu.org; Thu, 14 Jun 2007 21:03:21 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Hz0Dg-0005ek-Rb for emacs-devel@gnu.org; Thu, 14 Jun 2007 21:03:20 -0400 Original-Received: from agminet01.oracle.com ([141.146.126.228]) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Hz0Dd-0004pD-Qy; Thu, 14 Jun 2007 21:03:18 -0400 Original-Received: from rgmgw1.us.oracle.com (rgmgw1.us.oracle.com [138.1.186.110]) by agminet01.oracle.com (Switch-3.2.4/Switch-3.1.7) with ESMTP id l5F13F2h010509; Thu, 14 Jun 2007 20:03:15 -0500 Original-Received: from acsmt350.oracle.com (acsmt350.oracle.com [141.146.40.150]) by rgmgw1.us.oracle.com (Switch-3.2.4/Switch-3.1.7) with ESMTP id l5F13EW6014950; Thu, 14 Jun 2007 19:03:14 -0600 Original-Received: from dhcp-amer-csvpn-gw2-141-144-73-175.vpn.oracle.com by acsmt351.oracle.com with ESMTP id 2899635681181869285; Thu, 14 Jun 2007 18:01:25 -0700 X-Priority: 3 (Normal) X-MSMail-Priority: Normal X-Mailer: Microsoft Outlook IMO, Build 9.0.6604 (9.0.2911.0) In-Reply-To: X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3138 Importance: Normal X-Brightmail-Tracker: AAAAAQAAAAI= X-Brightmail-Tracker: AAAAAQAAAAI= X-Whitelist: TRUE X-Whitelist: TRUE X-detected-kernel: Linux 2.4-2.6 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:72911 Archived-At: > You seem bent on automatically converting all commands to > multi-commands. That might be useful, in a limited way. But > programmers will still need to be able to define multi-commands > that go beyond the simple case. I gave `icicle-search' as an > example. > > Would you please explain what is special about it? Ouch! It's a mother. I'd really appreciate it if you'd take a look at the doc for Icicles search and then take a look at the code for the functions. It would be a lot easier then to talk about it. I don't suggest that we need to start by taking all the stuff that `icicle-search' does into account, but I think it would be a good idea if you took a look, to see the kind of thing that might be done. IOW, let's start, as you already have, with the low-hanging fruit (80/20 rule), but you might want to take a look at the search stuff to get a picture of what's possible. I'd also suggest loading Icicles and giving `icicle-search' (`C-c`') a whirl. It's easier to experience that to read about. > > The need to replace commands is a complexity, and the code will > > be much better if we avoid that complexity. > > There is no need to replace any commands. Keep them all. > > As you have described it, Icicles replaces the command find-file. No, it doesn't replace it. If I gave that impression then I misspoke. What it does, if a user so chooses, is remap whatever keys `find-file' is bound to to `icicle-find-file'. Upon exiting Icicle mode, it undoes this remapping. > It does this by defining a new command (Icicle-find-file?) and remapping > remapping find-file to that. Yes, it remaps the command's key bindings. The command `find-file' is not redefined. > I think this complexity is unnecessary, and I want to try to avoid > installing it. Don't install it. I said, "There is no need to replace any commands." I said: > Speaking of replacement is off the mark. Multi-commands and the > ability to define them as appropriate for a given use are one > thing. Deciding to bind `C-x C-f' to a multi-command file-finding > function instead of vanilla `find-file' file is another thing - a > separate consideration. Forget the latter, if you will; it's not > necessary. Today, Icicles gives users the option to rebind `C-x C-f' to an Icicles command instead of `find-file'. We need not give users that option in the future. And if you build in multi-commandness, then there is absolutely no reason for such a rebinding - only the new, multi-command implementation of `find-file' will be needed. > The only purpose that I know of for defining Icicle-find-file is to > implement multi-command behavior. Is there any other reason? No, that is correct - it is the only reason. > I have proposed a modular and clean way to provide the multi-command > behavior, without the need to replace commands in this way. You said > that my proposal doesn't do the whole job. Maybe you are right, but I > need you to explain. What part of the job does it not do? Insofar as I understand it, it would do the whole job for commands such as `find-file'. Perhaps it could also do the whole job for any multi-commands that one can define today using macros `icicle-define-command' and `icicle-define-file-command'. I don't know. I haven't seen anything concrete, so I'm not sure how you will implement it. If it does everything that those macros do (or the equivalent), then it will make every command that calls `completing-read' or `read-file-name' (in the `interactive' spec at least) into a multi-command, and that will be a good thing. I'm not sure how you will proceed, but I'm sure it will be different from what I do today. The macros define a command of zero args that calls `completing-read' and applies the action function to the result. The minibuffer binding of `C-RET' also applies the action funtion to the current candidate. IIUC, in your approach, a user defines a command of one or more args, one arg of which is provided by a call to `completing-read' in the `interactive' spec (in one way or another). Then, whatever that command does to that arg in the command body is done to the current completion candidate when you use C-RET - that is, the entire command body is executed with the current candidate passed as the parameter. Is that it? And I assume that any other args keep their same values during this process. It might be that your approach will do everything that the macros currently do, just differently. It sounds good to me. > No one is against modularity. I have not seen a "proposed > implementation", beyond some vague hand-waving. > > I gave you an outline of the scheme. Of course I don't have all the > details. I am trying to work out the details but I need your help. I'll do my best to help where I can. > However, that needs to be done > carefully and fully. For example, use of a standalone > minibuffer and non-nil pop-up-frames should also work. > > I expect we can write the code in Fcall_interactively to do TRT in > those cases. The only way to make sure is to try it. Agreed. See below for my concerns about frame focus. > I agree about "independent of the specific command that was > run", but only in the case of run-of-the-mill multi-commands. > > Even if this only handles the run-of-the-mill multi-commands, and the > exceptions are handled by your macros, that is still a big > simplification. No, there is a misunderstanding. My macros, like your proposal, only handle the run-of-the-mill commands. To be more precise, they might be a bit less run-of-the-mill than your approach (I'm not sure of your approach), because they let you bind, in the definition of the action function itself, the action function etc. for a recursive call to `completing-read' or `read-file-name'. IOW, they recognize that particular function variable, `icicle-candidate-action-fn', whereas I'm not sure if your code will (I hope so). More generally, to allow a programmer to define a non-run-of-the-mill multi-command s?he needs to be able to bind: 1. `icicle-candidate-action-fn' - the action function 2. `icicle-candidate-alternative-action-fn' - an alternative action function 3. `icicle-delete-candidate-object' - a deletion action #1 is necessary to enable `C-RET', that is, to make it a multi-command at all. With your implementation of multi-commands, some such variable would still be necessary in the general case, to override use of the command body for the action function - that is, to provide a different action from what the command itself performs when you finally choose a candidate once and for all. One use case is defining a command that is itself called when defining another command. The first command might define a default action function if `icicle-candidate-action-fn' is nil when it is called. The second command can bind the action function to override the default in the command it calls. (There was an example of this, but I no longer have one to point to.) #2 is optional but required if you want to provide an alternative action (invoked by `C-S-RET' etc.). Icicles search is an example of a command where you can use the alternative action. The alternative action replaces all or part of the current search hit. (The main action visits the current search hit.) It is likely that there would be more Icicles commands in the future that would provide alternative actions. And a programmer can define custom commands that have alternative actions. #3 is optional but required if you want to provide a deletion action (invoked by `S-delete'). Today, there are several commands that provide a deletion action. You can bind this variable to either a deletion function or a variable whose value is a list of candidate objects (the object associated with the target candidate is deleted from the list variable). See this page for a description of #2 and #3: http://www.emacswiki.org/cgi-bin/wiki/Icicles_-_More_About_Multi-Commands. See this page for a description of Icicles search-and-replace using the alternative action: http://www.emacswiki.org/cgi-bin/wiki/Icicles_-_Search-And-Replace In sum, I think your approach will handle most cases. It might handle all cases handled by the macros. In the general case, a user would be able to bind the variables to arbitrary functions and define an arbitrary command that makes use of multi-commandness beyond the interactive spec. > And we can continue trying to make this mechanism > better; perhaps we can make it handle more of the commands. I'm not against such an effort. In fact, I find it interesting. My current assessment is that it is important for programmers to be able to specify an arbitrary function for #1. #2 and #3 could be considered nice-to-haves, but #2 is needed for Icicles search, unless that is built in somehow. Whether everything interesting can be cantoned to the `interactive' spec, I don't know. I'd like to be able to bind #1, #2, and #3 in an arbitrary context and call `completing-read' with those bindings current, to be able to use the different actions during completion. BTW, I should also mention that Icicles (optionally, but by default) uses a multi-command version of `execute-extended-command'. This code is a bit hairy. I think this feature is useful, but you might want to forego it if it is too complicated to implement in your design. You might be interested to take a look anyway. Perhaps you will see a way to do it in your approach, or perhaps it will inspire other thoughts. At least, the example it will give a flavor of using multi-command actions. The code is in icicles-cmd.el. The description is here: http://www.emacswiki.org/cgi-bin/wiki/Icicles_-_Multi_M-x. [BTW - I understand that you don't often have Web access. The complete doc (the same as is on the wiki) is also in files icicles-doc1.el and icicles-doc2.el in plain-text form (not HTML). The section headings are pretty much the same as the wiki page headings (URLs). So, for example, http://www.emacswiki.org/cgi-bin/wiki/Icicles_-_Multi_M-x corresponds to section "Icicles Multi `M-x'", in file icicles-doc1.el. So you can read up on this stuff if you are interested.] > For some multi-commands you > want the frame focus to end up in a different place when you > are done, for example. > > Could you tell me about one example? Maybe I can find a simple > general mechanism to handle this too. Let's not worry about this now. I'm not sure there will be a problem. What's probably the most important about this is written further below. > You might typically work in the buffer of application after using a > multi-command, or you might instead typically want the > minibuffer frame to continue to have the focus so you can use it > again - different commands have different use cases. > > Can you tell me about one example of each type, so I can see > why this is so? I can't now. I spent a while looking, but I can't seem to find what I thought I'd find. I think the general situation is this. It's easiest to follow if you think of pop-up-frames being non-nil, with a standalone minibuffer. 1. You invoke a multi-command. 2. You use `C-RET' on candidates. Each action might pop up a buffer in a different frame, giving it the focus - which is what you want in this case (often). 3. If you use C-g, then you typically want to return to the original buffer/frame. 4. You hit RET to finally choose a buffer/frame. You typically want the focus to end up there. You might, for #3 or #4, want the focus to be different, but I don't have a concrete example. I think perhaps what I was thinking of was that in defining action functions I sometimes need to put a `select-frame-set-input-focus' in the action function, either to force the focus to a frame associated with the current candidate or, on the contrary (and more typically), to force the focus to the minibuffer in preparation for another `C-RET'. If that is in fact the only use for this, then perhaps there is no problem. Presumably, your code would (1) keep the focus on the minibuffer and its frame during completion (i.e. for each `C-RET'), (2) leave the focus wherever the final `RET' found it or put it, and (3) put the focus back on the original buffer/frame in case of C-g or error. In some places, such as the multi `M-x', I do a few weird things perhaps, because I want the `C-RET' context to be just like a top-level context. But that might be irrelevant, and in any case it is not something to worry about now. > I had my multi-command definition macros available for my own use, > yet I did not use them to define some of the multi-commands. Why? > Because they are not flexible enough - they cannot be flexible > enough. There is no substitute for being able to code what is > needed in a particular case. > > Maybe that is true, but first let's make a reasonable effort to make a > general mechanism handle as much of the job as possible. Eventually > we may decide to handle a few hard cases with your macros. That sounds good to me. I think it would probably be advisable to at least have your basic handling respect bindings for an action, alternative action, and deletion functions. If that's available, then I think most of the flexibility needed will be provided. IOW, if your mechanism provides what the macros provide, then we're off to a good start. > Practically every place where I have used a non-nil value for > `icicle-use-candidates-only-once' is an example. It is not so > much that multiple invocation would be harmful (though perhaps > that can also be true for some commands). It is that, in many > cases, it is handy for the user to remove the candidate from > the list of available candidates, once it has been acted on. > > We could build that into the low-level mechanism too. That sounds good. > It would be > quite clean. Fcall_interactively just has to bind a certain variable > to nil, which holds a list of completion alternatives to exclude. > display-completion-list will ignore the alternatives in this list. > Then, each time around Fcall_interactively adds the proper argument > value to this list. But would the value still really be one of the possible completions, so that if you hit TAB or S-TAB again during the same invocation of `completing-read' it would show up again? That is the current behavior, and the behavior I prefer. Or else at least have some way to get that removed candidate back without starting all over. I want users to be able to do as much as possible on the fly, in the same invocation of `completing-read'. > We could control the feature with a character in the interactive spec, > as in (interactive "#bDelete Windows of buffer:") > where # specifies using candidates only once. That's fine, but for me that's getting ahead of ourselves at this point. If it helps you think about it, good. > FYI - wrt clicking the `delete' key to remove a candidate - > I've recently defined a complementary feature, to save a > candidate for later consideration. I haven't yet uploaded > this feature to the wiki, but I'll do > so soon, after testing things a bit more. FYI - I uploaded this new feature yesterday. I intend to change the binding (to `insert' from `C-insert'), but I've spent too much time on these emails! > These features seem interesting. I think they can all be implemented > cleanly in Fcall_interactively, but this suggests we might want to make > it call some Lisp code which would handle some of these cases. I'm in favor of Emacs doing stuff in Lisp, because I want to be able to hack it, and I don't hack C code (no fun for me, need to compile and build, etc.). I understand that doing stuff in C is good for performance. For me, this is a bit of an area of experimentation (UI experimentation), so I'd like to keep stuff in Lisp as much as possible, to let people explore and extend the ideas. That's just me. BTW, wrt using literal `interactive' specs (as opposed to a sexp that's eval'd in list arg to `interactive') - I've been advising Icicles users who write multi-commands (my implementation, not yours) not to use literal specs, because then using `M-*' (progressive completion: multiple match patterns) will require users to hit RET to exit each recursive minibuffer level separately. That is, because I put a `catch' in my version of `completing-read' and `read-file-name', when a user makes a final completion choice after using `M-*' I can throw the chosen value to the top. If a programmer instead uses a literal `interactive' spec then my `completing-read' code doesn't get called. This wouldn't be a problem for your code. You could make sure that `interactive' DTRT for a recursive minibuffer within `completing-read' etc. Just want to point out this use case. An alternative would be to implement `M-*' differently, and not use a recursive call to `completing-read' at all. In my implementation of `M-&', for instance, which is another form of progressive completion that lets you add predicates on the fly to narrow completion choices, I don't use a recursive call to `completing-read'. Instead, I modify the current `completing-read' predicate and then complete again (as in implicit TAB or S-TAB). I'm just pointing out that there might be different approaches for this kind of thing. > It's best to read about what Icicles search offers and how it > works, and then look at the code for `icicle-search' as an > example. I'll be glad to answer questions, but I don't want > to repeat here what is already written > elsewhere. Please see the links above. > > I will be glad to read the text you've already written, but finding > that text would be a pain for me. Could you please email it to me? See above: the doc is all in files icicles-doc1.el and icicles-doc2.el. Do you need me to email you the source files, or can you get them from Emacs wiki? On the wiki, the files are here, as well as easy ways to download them all: http://www.emacswiki.org/cgi-bin/wiki/Icicles_-_Libraries. It would help if you would read up some. It would sure cut down the needed back and forth by email. This is killing me. I can't imagine that anyone else is reading any of this. Also, if you want, we can take some of this off line if you think it bothers more than interests others.