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: Mon, 11 Jun 2007 11:33:40 -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 1181586888 25713 80.91.229.12 (11 Jun 2007 18:34:48 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Mon, 11 Jun 2007 18:34:48 +0000 (UTC) Cc: emacs-devel@gnu.org To: Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Jun 11 20:34:46 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 1Hxoiu-0007Y0-L7 for ged-emacs-devel@m.gmane.org; Mon, 11 Jun 2007 20:34:41 +0200 Original-Received: from localhost ([127.0.0.1] helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Hxoit-0000rF-Ga for ged-emacs-devel@m.gmane.org; Mon, 11 Jun 2007 14:34:39 -0400 Original-Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Hxoip-0000r8-Tm for emacs-devel@gnu.org; Mon, 11 Jun 2007 14:34:35 -0400 Original-Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Hxoio-0000qw-Ay for emacs-devel@gnu.org; Mon, 11 Jun 2007 14:34:34 -0400 Original-Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Hxoio-0000qt-4A for emacs-devel@gnu.org; Mon, 11 Jun 2007 14:34:34 -0400 Original-Received: from rgminet01.oracle.com ([148.87.113.118]) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1Hxoil-00040E-JH; Mon, 11 Jun 2007 14:34:31 -0400 Original-Received: from rgmgw3.us.oracle.com (rgmgw3.us.oracle.com [138.1.186.112]) by rgminet01.oracle.com (Switch-3.2.4/Switch-3.1.6) with ESMTP id l5BIYS11017903; Mon, 11 Jun 2007 12:34:29 -0600 Original-Received: from acsmt351.oracle.com (acsmt351.oracle.com [141.146.40.151]) by rgmgw3.us.oracle.com (Switch-3.2.4/Switch-3.1.7) with ESMTP id l5BGBRTR011735; Mon, 11 Jun 2007 12:34:28 -0600 Original-Received: from dhcp-amer-rmdc-csvpn-gw6-141-144-116-70.vpn.oracle.com by acsmt350.oracle.com with ESMTP id 2885912491181586840; Mon, 11 Jun 2007 11:34:00 -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: Importance: Normal X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.3028 X-Whitelist: TRUE X-Whitelist: TRUE X-Brightmail-Tracker: AAAAAQAAAAI= 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:72634 Archived-At: > If integrated with Emacs, this could be done by changing > `completing-read' etc. to act differently when `icicle-mode' > is on, unless that is a no-no. > > It is not out of the question to do this. However, it would be nicer > to find a cleaner way. Can you do most of these changes through key > bindings? Which changes are left, that can't be done that way (or not > cleanly)? Can we find non-ad-hoc ways of implementing them? I'd propose adding Icicles first as an optional library, without trying to integrate any of it deeply with Emacs. Later, we could look into a possible tighter integration. We might even want later to move some of the behavior to vanilla Emacs completion. The `completing-read' code is here: http://www.emacswiki.org/cgi-bin/wiki/icicles-fn.el. Perhaps others more familiar with Emacs implementation can advise whether some of this redefinition could or should be moved to the vanilla definition of `completing-read' or what might be a "cleaner way" to do what is done now this way. I would advise just leaving this code as is, at least for now. > it can replace some top-level commands with Icicles > versions (e.g. `find-file' with `icicle-find-file'). > I should be clear that this is not about redefining commands; it is about remapping their bindings: the bindings for `find-file' are mapped to `icicle-find-file'. > Why does it do this? Because those replacements are enhanced versions. They are typically multi-commands that 1) keep the same behavior as the original, as long as you don't use any special Icicles minibuffer bindings, but also 2) let you take advantage of those minibuffer bindings (e.g. `C-RET') to get the multi-command behavior. With the replacement, for instance, you can open any number of files, using completion, with one invocation of `C-x C-f', and you can optionally delete selected matching files on the fly (with `S-delete'). You can of course change your minibuffer input during that one invocation, to match different file names. (`M-k' clears the minibuffer.) Again, this binding replacement is, in any case, optional for a user (option `icicle-bind-top-level-commands-flag'), and it is only for `icicle-mode-map'. > > * Multi-commands: Define a command that acts on one foobar, > > and be able to use it also on multiple foobars in a single > > invocation. > > > > How is that implemented? > > A minibuffer key binding, `C-RET' (or `C-mouse-2' in > `completion-list-mode-map'), calls a command that acts on the > current completion candidate, where "current" is determined by > cycling or matching. > > How does it know what to call? Is it the same command that invoked > the minibuffer? Do you have to define a new function for this, > one for each command that uses the feature? A global variable, `icicle-candidate-fn', is bound to the function to use for the action. If it is bound to nil, then `C-RET' etc. are associated with the default action, which is to simply display individual help about the candidate. (The help action is also always available on `C-M-RET' etc.) Candidate help tries to DTRT, depending on the type of candidate (see command `icicle-help-on-candidate'). Yes, you must define a new command, in order to adapt a given existing command to multi-command use. This is a good thing, as some commands might not lend themselves well to multi-command use (i.e. it might make no sense for them, adding nothing). And, more often, it is appropriate for some commands to have a slightly different action function for candidates during completion than after completion (for instance, because the buffer/window/frame context or the use context might be different). The command used for the `C-RET' action can be any command. Sometimes `C-RET' performs the same action as the command invoking completion would carry out on the candidate chosen finally. Sometimes the action performed is a bit different or even quite different. The particular command and its context of use determines what is appropriate (most useful). The devil is in the details of the particular command and its use cases. We can generalize to some extent (that is what the multi-command-defining macros are for), but the best definition of a given multi-command should be decided case by case. Also, the command that invoked completion is not the same thing as the part of that command that actually acts on the candidate that is chosen - what I call the action function, bound to `icicle-candidate-action-fn'. Also, because of the difference in context (completion has not yet ended when the action is carried out), some window, buffer, etc. management needs to be taken into account. You can take a look at the multi-commands that I have defined. They are all in file icicles-cmd.el. You can find them by searching for any of these: 1. icicle-define-command 2. icicle-define-file-command 3. icicle-candidate-action-fn #1 and #2 are those multi-commands that use the same action function for final action and action during completion. #3 are other commands, which bind `icicle-candidate-action-fn' explicitly. The macro expansion of a multi-command defined using #1 or #2 is quite complex. Some of its definition implements context management (window, frame, buffer), and some of it implements treatment of possible errors from application of the action function. For example, the original buffer, window, or frame, to which we often want to return, might have been deleted by application of the action to a particular candidate (e.g. if the action is to kill the buffer, and the candidate acted on is the original buffer). And we usually want to keep the focus after action application on the minibuffer's frame, so that we can possibly keep using `C-RET' etc. on other candidates. To see what I mean about the complex definition, load icicles-cmd.el (not .elc) and then use `symbol-function' on a command defined with one of the macros. Or take a look at the macro definitions themselves, in icicles-mac.el. The optional alternative action function and the optional deletion-action are treated similarly. For instance, binding `icicle-candidate-alternative-action-fn' provides an alternative action, bound to `C-S-RET' etc. See http://www.emacswiki.org/cgi-bin/wiki/Icicles_-_Defining_Icicles_Commands for more about defining multi-commands. See http://www.emacswiki.org/cgi-bin/wiki/Icicles_-_Multi-Commands_the_Hard_Way for more about how the macros work. > It sounds like an ugly mechanism, What does? Why? > so if this feature is worth adding, > I would rather it be implemented differently. The cleanest way I can > think of is to set a flag telling call-interactively to call the > function then loop around, keeping the same prefix argument. Sorry, I don't understand this. Please elaborate. It "sounds like" you are redesigning without even being familiar with the design. I am not into redesigning Icicles or re-implementing the basic design. If others wish to do that later, that's another matter. A lot of time, testing, and use has gone into the current design and implementation. It works well, and I think it is quite clean. When not in Icicle mode, a user cannot tell that s?he was ever in it. And when in Icicle mode, s?he can still use Emacs in the same way as usual, with no real perception of a difference, as long as s?he doesn't use any of the extra minibuffer bindings. In some ways, the implementation is non-trivial - you don't want to make cavalier changes, and you must retest lots of scenarios after a fundamental change. Icicles is very general, which means that it has lots of different use scenarios. There are some global variables that hold various kinds of state, which means that some parts of the code are tightly coupled with other parts. I haven't done that gratuitously, but only when I felt it was necessary. That doesn't mean that there might not sometimes be a better way; it means only that one must be careful making changes to the core implementation. I'm not against making minor changes that I become convinced would be improvements, but I don't want to start over or possibly jeopardize things that work well by making fundamental changes that are not simple. Vague "do it this way instead" or "n'y a qu'a" suggestions won't convince me. If you want to discuss concrete implementation details, that's fine. I'm open to change, but I don't want to break things just because someone thinks s?he has a better idea (without making an effor to try out that idea or discuss it concretely). If Icicles does not break anything, and it does not have a lasting effect when you leave Icicle mode, then I think how it is implemented should not be a concern. How it is implemented can of course be examined to help determine if it breaks something. After FSF owns the code, others can take responsibility for breaking Icicles, if they like. Or I can continue to maintain it for FSF - which I prefer. I intend anyway to maintain and enhance my own version of Icicles, which I will continue to make available on Emacs Wiki. If my own version and the Emacs version begin to diverge so much that I cannot work on the former, then I'll go back to working on just the latter. > keeping the same prefix argument. Wrt prefix args: C-u is treated specially during completion, so that, for instance, you can apply it to individual candidates that you act on using `C-RET'. That is, you can use a different prefix argument each time you act on a candidate, if you like. Remember, that, by default, you can act on the same candidate multiple times. Sometimes that makes sense, sometimes it does not. You can bind `icicle-use-candidates-only-once-flag' to control this. See `icicles-mcmd.el' for the code (e.g. `icicle-universal-argument'). > This should work with ALL commands and avoid the need to define > separate multi-commands. Sorry, I don't agree. 1. It's not equally appropriate for all commands. It's not necessary for all commands. 2. It's appropriate, for many commands, to specialize the action behavior during completion. See the commands that explicitly bind `icicle-candidate-action-fn', as opposed to just using `icicle-define-command'. Command `icicle-search', for instance, could not be defined using `icicle-define-command'. > Once multi-commands are gone, does Icicles need to > redefine any commands? Is it just a matter of changes > inside completing-read? Sorry, I don't understand what you mean. Multi-commands will not be "gone". Multi-commandness will not be extended automatically to all commands. That is not appropriate. Are you asking for a list of Emacs commands that Icicles redefines when you are in Icicle mode (and restores when you exit that mode)? This is the list - it is also in the header of `icicles.el': completing-read, display-completion-list, exit-minibuffer, minibuffer-complete-and-exit, read-file-name, read-from-minibuffer, read-string, dabbrev-completion, lisp-complete-symbol, mouse-choose-completion, choose-completion-string, completion-setup-function, switch-to-completions, next-history-element (advised only), repeat-complex-command It's possible that some of these redefinitions could be moved to vanilla Emacs permanently. Typically, the original definition is extended only slightly. For instance, the `repeat-complex-command' definition is extended to read the command to be repeated using `completing-read', so that you can use completion on the history list and use `C-,' to sort the candidate list (in *Completions*) in different ways. If `icicle-bind-top-level-commands-flag' is non-nil, then various top-level bindings are redefined for use in Icicle mode - the list is in `icicles-mode.el'. In `icicle-mode-map', for example, `abort-recursive-edit' is remapped to `icicle-abort-minibuffer-input'. The original binding is restored when Icicle minor mode is exited. As another example, `completion-setup-function' is modified so that it does not print the help lines at the top of *Completions*. That printing is done instead in `display-completion-list', so that the *Completions* window can be fit to the buffer. Icicles formats the *Completions* display "intelligently", determining a useful number of columns and height, and it fits the window to the formatted buffer. (This formatting, e.g. column spread and default window width, is under the control of user options.) That is an enhancement that we might want to consider for vanilla Emacs. As a third example, `switch-to-completions' is extended to always select the *Completions* window, even when it is on another frame. In sum, any attempt to integrate such changes tightly with the vanilla Emacs code needs to be done on a case-by-case basis. I suggest that there is no need to do that at all now, but it could be done over time, if some such extensions were deemed useful to vanilla Emacs also.