emacs-devel
[Top][All Lists]
Advanced

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

RE: propose adding Icicles to Emacs


From: Drew Adams
Subject: RE: propose adding Icicles to Emacs
Date: Wed, 13 Jun 2007 12:00:20 -0700

I'm not sure it's worth going into each of your comments, but I'll try.

Please see my previous email (with Plan A and Plan B). That is my position
and a starting point for discussion about how to proceed. (I received this
mail after sending my previous mail, BTW.)

>     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.
>
> That is a very bad idea.  "Temporary" solutions tend to become
> permanent, and to prevent that from occurring requires insistence.  No
> software developer should install code meant to be temporary unless it
> is essential to do so.  Icicles features are nice, but installing them
> is not essential.

Installing Icicles features is not essential to Emacs. We agree on that.

Evolution, even planned evolution, can proceed in stages. A stage that
includes Icicles as an optional package is not equivalent to ugly hacking or
sneaking in a trojan horse under the pretense or belief that it is only
temporary. I gave good reasons for my recommendation. It is not a good idea
to lay waste to everything first, IMO, but that is your call. You are
welcome to prefer plan B. In plan B, Icicles is a quarry of ideas, you are
the implementor, and I can be consulted if you have questions.

> Therefore we will put the code into the form we want to keep
> permanently and then install it.
>
>     > 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.
>
> Let's suppose I can magically implement multi-command behavior without
> the need to define separate multi-commands to do it.  (I think I can,
> and I explained how.)

You did _not_ explain how, beyond some hand waving. At least not to my
satisfaction. I don't understand your magic solution, and I think you don't
fully understand Icicles multi-command behavior. But if you choose plan B, I
don't necessarily need to understand your design, except to be able to
answer questions about the existing Icicles features.

If you don't want to explain it, you can implement it and we can then talk
about how it fits with Icicles features and what parts of Icicles could
perhaps be eliminated because of it.

Creating a multi-command is a programmer decision. Different multi-commands
work differently. The simplest just do what you have understood. But even in
the simplest cases, which can be handled by the Icicles definition macros, a
programmer can (and will sometimes need to) provide extra bindings or extra
code.

> Is there any other reason in icicles to define new commands
> to replace the existing ones?

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.

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.

I do agree that much of the error and context handling that I add to a
multi-command definition via the definition macros could instead be built
into Emacs somehow, and that would be great.

Only please do that carefully, if you do it, and please still let
programmers bind their own candidate action function when they design a
custom multi-command. Without that feature, a lot is lost. As I said before,
you have only to look at the commands that explicitly bind
`icicle-candidate-action-fn' or `icicle-candidate-alt-action-fn' to get an
idea why this is needed. Again, `icicle-search' is a good example.

IOW, if you decide to build some magic into Emacs to implement some of the
multi-command functionality, please keep it flexible, so that Emacs-Lisp
programmers can build custom multi-commands that use different action
functions etc.

You know, there are other things that could also be moved into vanilla Emacs
as well (outside of using an Icicles package). Multi-commands depend on
candidate cycling (to be more precise, they cry out for it, but it is not a
strict logical requirement). The cycling logic is another thing that could
be provided by Emacs outside of Icicles. We are moving in the direction of
Plan B here.

> If so, what is it?
> Maybe I can find a better way to implement that, too.

Not sure what this means. I've said that we need not automatically replace
any command bindings. If users want to bind `C-x C-f' to a different
command, they can always do so. Even in Icicles, I don't force this on
anyone: a user option controls such command remapping.

> 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.

>     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).
>
> That is no argument against making multi-command behavior magic.
> Just respond, "If it isn't useful there, don't use it there."

Multi-commandness being inappropriate for a given command is one thing. Yes,
it should be possible to optionally not use multi-commandness, when that is
appropriate. That is what happens anyway now: by default, no action function
is defined, and C-RET provides candidate help (just as C-M-RET does).

The more important consideration is the following:

>     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).
>
> This might be a real issue.  Can you please give an example or two?

I did. `icicle-search'. And the other multi-commands that are defined by
explicitly binding an action function, alternate action function, or
candidate-help function, instead of being defined using a definition macro.

There are several multi-commands that are, themselves, built using
`icicle-search'. You can read about Icicles search here:

http://www.emacswiki.org/cgi-bin/wiki/Icicles_-_Search_Commands%2c_Overview

http://www.emacswiki.org/cgi-bin/wiki/Icicles_-_Search-And-Replace

http://www.emacswiki.org/cgi-bin/wiki/Icicles_-_Other_Search_Commands

The `icicle-search' code is here:
http://www.emacswiki.org/cgi-bin/wiki/icicles-cmd.el

>     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.
>
> That is true if you distribute it separately.
> If it is part of Emacs, that changes everything.
> We want Emacs to be modular.  My proposed implememtation
> of multi-command behavior is totally modular.  I think we
> can make it work with NO changes in any specific command.

No one is against modularity. I have not seen a "proposed implementation",
beyond some vague hand-waving. I'm not against simplification. I'm asking
for details, so I can understand you. My ideas are detailed in the
implementation. You can examine exactly how it is done now and propose
alternatives. Your proposal so far is, for me, something indeterminate and
uncommunicated.

>     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.
>
> The code in call-interactively may need to deal with such cases.  I
> think it can do so in ways that are independent of the specific
> command that was run.

I agree that some of what is currently done in the definition macros (hence,
in the code of each multi-command defined with them) could be built into
Emacs - perhaps to handle all commands. 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 agree about "independent of the specific command that was run", but only
in the case of run-of-the-mill multi-commands. For some multi-commands you
want the frame focus to end up in a different place when you are done, for
example. 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. There needs to be some flexibility. A programmer needs
to be able to build a custom multi-command in the sense I have described.

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.

>     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.
>
> I just assumed it was the other way.  We could handle the prefix this
> way just as easily.

Yes, this is the kind of thing that could advantageously be handled
automatically within the command loop (or whatever) of Emacs itself.

I think what I'm trying to say is that, yes, the infrastructure to interpret
multi-command definitions and handle multi-command bindings such as `C-RET'
could be built into Emacs, simplifying or eliminating, for example, the need
for the multi-command definition macros.

But programmers will still need a flexible way to direct and inform that
infrastructure, so that they can define custom multi-commands that DTRT in
different contexts. They need, at a minimum, a way to define the action
function, the alternative action function, the candidate-help function, and
object deletion for a given multi-command. There can be default behavior,
such as using the same action for both C-RET and RET and having an empty
alternative action, but programmers need to be able to override this default
behavior and provide their own functions for these things.

>     Remember, that, by default, you can act on the
>     same candidate multiple times. Sometimes that makes sense,
>     sometimes it does not.
>
> Can you give me an example where it does not make sense?

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.

That is the purpose of `icicle-use-candidates-only-once'. This does not
definitively prevent using the candidate again in the same multi-command
invocation; it simply removes it from the candidate list for the time being,
so that you don't see it and you cannot cycle to it. If you complete again
(TAB or S-TAB), however, then you see the candidate again. This is exactly
the same behavior a user gets if s?he explictly uses the `delete' key or
`S-mouse-2' on the current completion candidate: it is simply removed as a
candidate (until you complete again).

For instance, command `icicle-set-option-to-t' reads the name of a binary
user option and sets it to t. It doesn't make much sense to do this more
than once to the same option in the same command invocation. Removing that
option from the list of candidates makes it easier to see the remaining
options that you can act on.

A case such as `icicle-delete-windows' is more along the lines of "if it's
done, it's done". Once you have deleted the windows showing a buffer, it
makes sense to remove that buffer name from the list of candidates, because
it makes no sense to choose it again. `icicle-delete-file' is similar: if
the file has been deleted, you should no longer see it as a candidate. (Some
multi-commands remove a used candidate directly, without employing
`icicle-use-candidates-only-once' to do that.)

BTW, it might seem that commands such as `icicle-find-file' might also want
to bind this option to non-nil. But a user might, in the same
`icicle-find-file' invocation, navigate among different files using
`C-RET' - that is, return to choose the same file name more than once. To
bind this option in any given context, it should not be the case that a user
might want to return to a given candidate and use it again.

BTW2: There is a difference between removing a candidate as a candidate and
removing (deleting) the object that the candidate names. If the candidate is
a file name for `icicle-delete-file', then the associated file is deleted by
the action function. In Icicles, you can also provide any multi-command with
a separate deletion action (invoked by `S-delete'), which deletes some
object associated with the candidate (name). Command `icicle-buffer', for
instance, uses `switch-to-buffer' as its action function and
`icicle-kill-a-buffer' as its deletion action - `C-RET' invokes the former
and `S-delete' invokes the latter.

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.

This new feature lets you act more carefully than you might be prone to
using multi-command actions. You can choose a set of candidates (in several
ways, including choosing individual candidates to add) and then, later, take
a good look at that set and then act on all candidates at once. Think of
this as filling out a checklist and then later submitting it for action -
the way that Dired marked files work, for instance. In Icicles, you have
always been able to save the current set of matching candidates (to a
variable or a cache file) and to act on all set members. What I've added
recently is the ability to add additional members to such a saved set
(individually or as a set union).

>     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'.
>
> Can you please explain an example of this specialization?
> Then I can think about its consequences.

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.







reply via email to

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