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: Mon, 2 Jul 2007 15:19:11 -0700

>     You say, "And [the command] can do something different if it
>     wants to." That was precisely my point. Somehow, someone needs
>     to tell it whether, and if so how, to let users do something
>     different, if that is appropriate for that particular command.
>
> The programmer will do this by checking a flag that `interactive' will
> provide as an argument.

That covers "whether", but not "how". Programmers should be able to specify
just what the set-as-a-whole operation does and how. In the case of
customize-face, for instance, it combines the face widgets in the same
Customize buffer. The relation between the action that is to be applied to
an individual object and the action to be applied to a list of such objects
is not obvious or fixed - or at least it should not be, IMO.

>     The question is _how_ a programmer can indicate which
>     function, if any, to apply to the entire list (as a whole) and
>     which function, if any, to apply to each set member individually
>     (all or selected members only). In some cases it makes sense to
>     let users do one, in some cases the other, and in
>     some cases both (separately).
>
> No, that's not the question.  The question is how a programmer can
> implement the desired behavior in each case.

You say "how to implement", and I say "how to indicate which function" -
tomayto, tomahto. Even if you don't use a Lisp function to implement the
behavior, the need is the same: be able to say what will be done and how.
Let's not get bogged down too much by terminology (if we do in fact
understand each other).

> With my proposal, the programmer will make the command get an
> argument saying which behavior to use.
> Here's one idea:  use ! in the interactive spec to mean
>
>    if the user uses the multi-command feature for this
>    argument, read all the argument values, make a list of them,
>    and pass that as the argument.

What do you mean by "uses the multi-command feature"? Do we agree that the
user would have different keys to invoke each of: (1) an action on the
current candidate, (2) an action on each matching candidate, individually,
and (3) an action on all matching candidates, taken together? I think you're
speaking only of the #3 "multi-command feature" here, right?

> It would look like this:
>
> (defun command (file)
>   (interactive "!fFile: ")
>   (if (listp file)
>       ...operate on list of files...
>     ...operate on one file...))

That's one possible way. Can I assume that users can also apply the one-file
action to all matching files, as is the case today with `C-!'? That is, they
can still do #2 above, right?

Your approach makes each command definition that uses "!" in the interactive
spec deal with the list (collective) and non-list (individual) cases
together, in a conditional in its body. In my approach, the main code of the
command (the single-item case) is what fills the command definition, and the
definition of the action for the list of files is defined as a separate
function. Which is clearer or otherwise better?

(defun command (file)
  (interactive "fFile: ")
  (let ((all-candidates-action-fn 'action-all))
     ...operate on one file...))

(defun action-all (files)
  ...operate on list of files...)

This still assumes your automatic treatment of multicommands via
`call-interactively'. The way I do it now separates each of the action
functions (the action "implementations", in your terms) from the command
definition itself:

(defun command ()
  (interactive)
  (let ((candidate-action-fn 'action-one)
        (all-candidates-action-fn 'action-all))
     (action-one (read-file-name "File: "))))

(defun action-one (file)
  ...operate on one file...))

(defun action-all (files)
  ...operate on list of files...)

In the general case, you can do something more or aomething different in the
`command' than just apply `action-one' to the file name that is read.

In the simplest case, `command' just binds the action functions, reads with
completion, and applies the main action to what is read. That is, `command'
is essentially an interface. In the simplest case, the body of `command'
looks like a definition of a simple command to act on one object (file).
Most Icicles multicommands will look just like the corresponding simple
commands, with `icicle-define-command' instead of `defun'.

In your approach, too, the simple case is simple. But in the general case,
all of the code for each of the various actions would presumably be in the
`command' body, in one big conditional. I'm not sure that's an improvement,
for programmers.

Anyway, I'm not against such an approach. I'm just saying that I'm not yet
convinced it is an improvement. Of course, you don't need to convince me.

> When using a Lisp expression inside `interactive',
> it could look like this:
>
> (defun command (file)
>   (interactive
>     (list (multi-arg-repeat
>           (read-file-name ...))))
>   (if (listp file)
>       ...operate on list of files...
>     ...operate on one file...))
>
> where `multi-arg-repeat' is a suitable macro
> that expands into something like
>
>    (multi-arg-repeat-internal (lambda () (read-file-name ...)))

I don't know what you have in mind for `multi-arg-repeat(-internal)'.

I really don't have any special suggestions about this. In general, I think
it's easier for a programmer to think in terms of separate action functions
for each of the things we've talked about:

1. help action        on current candidate
2. main action        on current candidate
3. alternative action on current candidate
4. deletion action    on current candidate
5. main action        on list of matching candidates
6. alternative action on list of matching candidates

We haven't actually talked about #6, but it is a logical feature, from the
moment that you allow for #3 and #5. The user can today apply the main
action (#2) or the alternative action (#3) to all matching candidates,
acting on each individually. No extra function needs to be defined for this;
#2 and #3 do the job. What you've brought up is #5: acting on all
collectively. I've added #6 here.

In my approach, which I think is maybe simpler for programmers, each of
#1-#6 is a predefined variable that you bind to the function you want. If a
variable is not bound or is bound to nil, then nothing happens when the user
invokes the corresponding key. More precisely, if #1 and #2 are not bound,
then candidate help is provided in a default way (which is nevertheless
specific to each candidate type).

If you think that what you've described is the best approach, then go for
it. I hope that you will still allow for all of #1-#4, at least.

As I said earlier, this (#5, and in fact the whole question of how to
implement multicommands) is peripheral to most of what could be integrated
from Icicles.







reply via email to

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