unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Suggestion: Simple way to make conditional key bindings.
@ 2002-08-23 12:05 Kim F. Storm
  2002-08-26  0:36 ` Richard Stallman
  0 siblings, 1 reply; 17+ messages in thread
From: Kim F. Storm @ 2002-08-23 12:05 UTC (permalink / raw)



Sometimes you would like a specific key binding to be controlled
by some global or local state, but you really don't want to mess
with minor-mode keymaps etc.

The following method - illustrated by example - is simple, yet very
powerful and flexible.

The basic idea is to interpret a '(cond ...) binding "the natural way":

(setq a nil b nil c nil)
(global-set-key [f11] 
		'(cond
		  (a delete-char)
		  (b find-file)
		  (c nil)
		  (t (keymap (?a . "abc") (?b . "bcd")))))
[f11 a] => "abc"
[f11 b] => "bcd"
[f11 c] => undefined

(setq c t)
[f11] => undefined

(setq b t)
[f11] => find-char

(setq a t)
[f11] => delete-char


Here is a patch [against a fairly old keymap.c] to implement this feature.
The simplicity of the approach is proven by the size of the patch :-)


One use would be to bind C-y to `yank' except when the first element
in the kill-ring is a table, in which case we want to run
`yank-with-properties':


(global-set-key "\C-y"
        '(cond
          ((and kill-ring (table-recognize-table (car kill-ring)))
            yank-with-properties)
          (t yank)))


One advantage (IMO) is that C-h k C-y will report yank or
yank-with-properties depending on the actual function taken if
you hit C-y.

WDYT ?



Index: keymap.c
===================================================================
RCS file: /cvs/emacs/src/keymap.c,v
retrieving revision 1.260
diff -c -r1.260 keymap.c
*** keymap.c	10 May 2002 23:57:14 -0000	1.260
--- keymap.c	13 May 2002 10:08:23 -0000
***************
*** 93,98 ****
--- 93,99 ----
  Lisp_Object Vdefine_key_rebound_commands;
  
  Lisp_Object Qkeymapp, Qkeymap, Qnon_ascii, Qmenu_item, Qremap;
+ Lisp_Object Qcond;
  
  /* Alist of elements like (DEL . "\d").  */
  static Lisp_Object exclude_keys;
***************
*** 690,695 ****
--- 691,718 ----
  	    return object;
  	}
  
+       /* If the keymap contents looks like (cond (COND DEFN)...)
+ 	 then find first non-nil COND and use its DEFN.*/
+ 
+       else if (EQ (XCAR (object), Qcond))
+ 	{
+ 	  register Lisp_Object args = XCDR (object);
+ 	  object = Qnil;
+ 	  for ( ; CONSP (args); args = XCDR (args))
+ 	    {
+ 	      register Lisp_Object clause, val;
+ 	      clause = XCAR (args);
+ 	      if (!CONSP (clause) || !CONSP (XCDR (clause)))
+ 		continue;
+ 	      val = menu_item_eval_property (XCAR (clause));
+ 	      if (!NILP (val))
+ 		{
+ 		  object = XCAR (XCDR (clause));
+ 		  break;
+ 		}
+ 	    }
+ 	}
+ 
        /* If the keymap contents looks like (STRING . DEFN), use DEFN.
  	 Keymap alist elements like (CHAR MENUSTRING . DEFN)
  	 will be used by HierarKey menus.  */
***************
*** 3650,3655 ****
--- 3673,3681 ----
  
    Qremap = intern ("remap");
    staticpro (&Qremap);
+ 
+   Qcond = intern ("cond");
+   staticpro (&Qcond);
  
    remap_command_vector = Fmake_vector (make_number (2), Qremap);
    staticpro (&remap_command_vector);





-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
@ 2002-08-23 12:52 David PONCE
  0 siblings, 0 replies; 17+ messages in thread
From: David PONCE @ 2002-08-23 12:52 UTC (permalink / raw)
  Cc: emacs-devel

Hi Kim,

> Sometimes you would like a specific key binding to be controlled
> by some global or local state, but you really don't want to mess
> with minor-mode keymaps etc.
>
[...]
>
> One use would be to bind C-y to `yank' except when the first element
> in the kill-ring is a table, in which case we want to run
> `yank-with-properties':
>
>
> (global-set-key "\C-y"
>         '(cond
>           ((and kill-ring (table-recognize-table (car kill-ring)))
>             yank-with-properties)
>           (t yank)))
>
>
> One advantage (IMO) is that C-h k C-y will report yank or
> yank-with-properties depending on the actual function taken if
> you hit C-y.
>
> WDYT ?

It seems that you can do something similar this way:

(global-set-key "\C-y" '(menu-item "my-filter" :filter my-filter))

(defun my-filter (&rest ignore)
  (cond
   ((and kill-ring (table-recognize-table (car kill-ring)))
    'yank-with-properties)
   (t 'yank)))

Am I wrong?

Sincerely,
David

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
       [not found] <3D49FF140074EFAE@mel-rta7.wanadoo.fr>
@ 2002-08-23 13:16 ` Kim F. Storm
  2002-08-23 17:22   ` Stefan Monnier
  0 siblings, 1 reply; 17+ messages in thread
From: Kim F. Storm @ 2002-08-23 13:16 UTC (permalink / raw)
  Cc: emacs-devel

"David PONCE" <David.Ponce@wanadoo.fr> writes:

> > (global-set-key "\C-y"
> >         '(cond
> >           ((and kill-ring (table-recognize-table (car kill-ring)))
> >             yank-with-properties)
> >           (t yank)))
> > 
> > 
> 
> It seems that you can do something similar this way:
> 
> (global-set-key "\C-y" '(menu-item "my-filter" :filter my-filter))
> 
> (defun my-filter (&rest ignore)
>   (cond
>    ((and kill-ring (table-recognize-table (car kill-ring)))
>     'yank-with-properties)
>    (t 'yank)))
> 
> Am I wrong?

Not at all [that's more or less how it is implemented].

But IMO, the `menu-item' syntax is awful, and using a
filter function is an added complexity which is pretty
unflexible.


I failed to mention a very important benefit of integrating this in
the keymaps directly:

It will then be quite trivial to enhance `define-key' to handle
conditional bindings:

(define-key global-map "\C-y" 'yank)  ; this sets the default

(define-key global-map "\C-y" 'yank-with-properties
        '(and kill-ring (table-recognize-table (car kill-ring))))

The second call would automatically changes the non-cond binding into
a cond binding with the previous binding as default.


To remove a conditional binding, we could use either of
the following:

(define-key global-map "\C-y" 'yank-with-properties t)

(define-key global-map "\C-y" nil
        '(and kill-ring (table-recognize-table (car kill-ring))))


Removing the last condtional binding could collapse the 
resulting (cond ((t yank))) back into 'yank.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-23 13:16 ` Suggestion: Simple way to make conditional key bindings Kim F. Storm
@ 2002-08-23 17:22   ` Stefan Monnier
  2002-08-25 23:33     ` Kim F. Storm
  0 siblings, 1 reply; 17+ messages in thread
From: Stefan Monnier @ 2002-08-23 17:22 UTC (permalink / raw)
  Cc: David PONCE, emacs-devel

> > > (global-set-key "\C-y"
> > >         '(cond
> > >           ((and kill-ring (table-recognize-table (car kill-ring)))
> > >             yank-with-properties)
> > >           (t yank)))
> > > 
> > > 
> > 
> > It seems that you can do something similar this way:
> > 
> > (global-set-key "\C-y" '(menu-item "my-filter" :filter my-filter))
> > 
> > (defun my-filter (&rest ignore)
> >   (cond
> >    ((and kill-ring (table-recognize-table (car kill-ring)))
> >     'yank-with-properties)
> >    (t 'yank)))
> > 
> > Am I wrong?
> 
> Not at all [that's more or less how it is implemented].
> 
> But IMO, the `menu-item' syntax is awful, and using a

If the problem is only syntax, feel free to create an appropriate macro.

> filter function is an added complexity which is pretty
> unflexible.

What do you mean by `complexity' ?
You want to have a code.  That's what functions are for.  I think `eval'
should generally be avoided, and `funcall' used instead.
This is especially true if we care about lexical scoping.

One problem with your change is "what binding do we use when we don't want
to run code?".  The `menu-item' syntax provides a binding (in the example
above it's "my-filter" which is not very useful indeed) for the case
where code should not be evalled (for example in `where-is').

> It will then be quite trivial to enhance `define-key' to handle
> conditional bindings:

But is it desirable ?

> (define-key global-map "\C-y" 'yank)  ; this sets the default
> 
> (define-key global-map "\C-y" 'yank-with-properties
>         '(and kill-ring (table-recognize-table (car kill-ring))))
> 
> The second call would automatically changes the non-cond binding into
> a cond binding with the previous binding as default.

Why not

  (define-key global-map "\C-y" 'yank-careful)
  (defun yank-careful (...)
    "Reinsert the last stretch of killed text, like `yank'.
  Contrary to `yank' this function is careful to preserve some important
  text properties when yanking tables."
    ...)

The advantage is that C-h k C-y doesn't just give you one of the two
bindings but a docstring that describes both.  Of course we could also
improve C-h k to recognize your `cond' construct, etc... but is it
really worth the trouble ?


	Stefan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-23 17:22   ` Stefan Monnier
@ 2002-08-25 23:33     ` Kim F. Storm
  2002-08-26 15:47       ` Stefan Monnier
  0 siblings, 1 reply; 17+ messages in thread
From: Kim F. Storm @ 2002-08-25 23:33 UTC (permalink / raw)
  Cc: David PONCE, emacs-devel

"Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes:

> > 
> > But IMO, the `menu-item' syntax is awful, and using a
> 
> If the problem is only syntax, feel free to create an appropriate macro.
> 
> > filter function is an added complexity which is pretty
> > unflexible.
> 
> What do you mean by `complexity' ?

Using code is not "self-contained"; in contrast, key bindings made by
one elisp package is typically independent of the key bindings made by
other packages.  So using code is more complex than key bindings.

> You want to have a code.  That's what functions are for.  I think `eval'
> should generally be avoided, and `funcall' used instead.
> This is especially true if we care about lexical scoping.

I don't quite follow, but I take your word for it :-)

> 
> One problem with your change is "what binding do we use when we don't want
> to run code?".  The `menu-item' syntax provides a binding (in the example
> above it's "my-filter" which is not very useful indeed) for the case
> where code should not be evalled (for example in `where-is').

Who said we don't want to run code :-)

Ok, I can see that could be a problem if we cache the result.
But I guess we can just use the "default" binding, i.e. the last
element (t ...) in the cond [and nil if no such element is present].

> 
> > It will then be quite trivial to enhance `define-key' to handle
> > conditional bindings:
> 
> But is it desirable ?

Don't really know...   It seems like a simple approach to allow
packages to hook into "standard bindings".

> 
> > (define-key global-map "\C-y" 'yank)  ; this sets the default
> > 
> > (define-key global-map "\C-y" 'yank-with-properties
> >         '(and kill-ring (table-recognize-table (car kill-ring))))
> > 
> > The second call would automatically changes the non-cond binding into
> > a cond binding with the previous binding as default.
> 
> Why not
> 
>   (define-key global-map "\C-y" 'yank-careful)
>   (defun yank-careful (...)
>     "Reinsert the last stretch of killed text, like `yank'.
>   Contrary to `yank' this function is careful to preserve some important
>   text properties when yanking tables."
>     ...)

The point is that you can install a package - like table.el - which is
then able to install its own conditional binding on C-y *without*
interferring with (or even knowning) the standard binding.

Suppose we have a conditional binding like this

  (define-key global-map "\C-y" 'yank-rectangle
        '(rectangle-p (car kill-ring)))

to be able to insert rectangles from the kill-ring using C-y.

Then table.el would still be able to install its own conditional
binding on C-y.


> 
> The advantage is that C-h k C-y doesn't just give you one of the two
> bindings but a docstring that describes both.  Of course we could also
> improve C-h k to recognize your `cond' construct, etc... but is it
> really worth the trouble ?

I didn't think about that, but it would be a nice way to report such
"multiple" bindings on a key...

But you may also consider this as a different approach than using a
minor-mode-keymap, and in that case, I think C-h k doesn't report all
possible bindings for a key -- only the "currently active" binding, so
why does `cond' have to behave differently?

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-23 12:05 Kim F. Storm
@ 2002-08-26  0:36 ` Richard Stallman
  2002-08-26 16:21   ` Stefan Monnier
  0 siblings, 1 reply; 17+ messages in thread
From: Richard Stallman @ 2002-08-26  0:36 UTC (permalink / raw)
  Cc: emacs-devel

    (global-set-key [f11] 
		    '(cond
		      (a delete-char)
		      (b find-file)
		      (c nil)
		      (t (keymap (?a . "abc") (?b . "bcd")))))

I agree that this is convenient.  The question is, is it better to
make this a primitive facility, as you suggested, or to add a macro to
do the job using menu-item, as Stefan suggested?

Using menu-item has an advantage that we use a function rather than
a form.  It also has the advantage of not adding any complexity
to the key binding data structures.

But those are not the only factors; others may be more important.

    One advantage (IMO) is that C-h k C-y will report yank or
    yank-with-properties depending on the actual function taken if
    you hit C-y.

If we use menu-item, what will C-h c say? 

    One problem with your change is "what binding do we use when we don't want
    to run code?".  The `menu-item' syntax provides a binding (in the example
    above it's "my-filter" which is not very useful indeed) for the case
    where code should not be evalled (for example in `where-is').

I think we do want where-is to find this binding, though.

      (define-key global-map "\C-y" 'yank-careful)
      (defun yank-careful (...)
	"Reinsert the last stretch of killed text, like `yank'.
      Contrary to `yank' this function is careful to preserve some important
      text properties when yanking tables."
	...)

    The advantage is that C-h k C-y doesn't just give you one of the two
    bindings but a docstring that describes both.

I think that sometimes this will be better, but sometimes it will be
better for C-h k to give the doc string for the specific command
that will be executed.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-25 23:33     ` Kim F. Storm
@ 2002-08-26 15:47       ` Stefan Monnier
  2002-08-26 19:33         ` Miles Bader
  2002-08-27 11:23         ` Kim F. Storm
  0 siblings, 2 replies; 17+ messages in thread
From: Stefan Monnier @ 2002-08-26 15:47 UTC (permalink / raw)
  Cc: Stefan Monnier, David PONCE, emacs-devel

> > You want to have a code.  That's what functions are for.  I think `eval'
> > should generally be avoided, and `funcall' used instead.
> > This is especially true if we care about lexical scoping.
> 
> I don't quite follow, but I take your word for it :-)

When you construct a function, the Elisp interpreter/compiler knows that
it's a piece of code and can do all kinds of things with it (byte-compile
it, analyze it and put out warnings, build a closure to remember the
current lexical bindings, ...).
OTOH, when you build a piece of code to be eval'd, the Elisp
interpreter/compiler usually has no idea that this is code rather
than just some kind of list of elements, so it can't do anything
clever with it.

> > One problem with your change is "what binding do we use when we don't want
> > to run code?".  The `menu-item' syntax provides a binding (in the example
> > above it's "my-filter" which is not very useful indeed) for the case
> > where code should not be evalled (for example in `where-is').
> 
> Who said we don't want to run code :-)

The current code says so.

> > > It will then be quite trivial to enhance `define-key' to handle
> > > conditional bindings:
> > 
> > But is it desirable ?
> 
> Don't really know...   It seems like a simple approach to allow
> packages to hook into "standard bindings".

How about a set of examples where the current code does not provide
sufficient flexibility ?  I can come up with plenty of examples
where we could use your code, but for most/all of them we could
just as well put the bindings in minor/major-mode-maps or text-property
keymaps.

> > > (define-key global-map "\C-y" 'yank)  ; this sets the default
> > > 
> > > (define-key global-map "\C-y" 'yank-with-properties
> > >         '(and kill-ring (table-recognize-table (car kill-ring))))
> > > 
> > > The second call would automatically changes the non-cond binding into
> > > a cond binding with the previous binding as default.
> > 
> > Why not
> > 
> >   (define-key global-map "\C-y" 'yank-careful)
> >   (defun yank-careful (...)
> >     "Reinsert the last stretch of killed text, like `yank'.
> >   Contrary to `yank' this function is careful to preserve some important
> >   text properties when yanking tables."
> >     ...)
> 
> The point is that you can install a package - like table.el - which is
> then able to install its own conditional binding on C-y *without*
> interferring with (or even knowning) the standard binding.

I don't think that's right.  I don't believe that table wants to override
C-y sometimes: instead it wants to override `yank' sometimes.
So what you want to do is to create `yank-careful' and then use
either the `remap' thingy or substitute-key-definition or something
like that.

> Suppose we have a conditional binding like this
> 
>   (define-key global-map "\C-y" 'yank-rectangle
>         '(rectangle-p (car kill-ring)))
> 
> to be able to insert rectangles from the kill-ring using C-y.

The behavior would be really odd if the user had rebound C-y
to `comment-dwim'.

> Then table.el would still be able to install its own conditional
> binding on C-y.

Now that's a more interesting example.  But maybe that calls for
replacing `yank-careful' with a (defadvice yank ...) or something
like that.  I admit that I don't think either of yank-careful or
defadvice are quite satisfactory for this case.
But maybe, using `remap', we could check for an existing `remap'
binding before adding our own, so that table.el would not defer
to `yank' but to `yank-careful'.

> > The advantage is that C-h k C-y doesn't just give you one of the two
> > bindings but a docstring that describes both.  Of course we could also
> > improve C-h k to recognize your `cond' construct, etc... but is it
> > really worth the trouble ?
> 
> I didn't think about that, but it would be a nice way to report such
> "multiple" bindings on a key...
> 
> But you may also consider this as a different approach than using a
> minor-mode-keymap, and in that case, I think C-h k doesn't report all
> possible bindings for a key -- only the "currently active" binding, so
> why does `cond' have to behave differently?

It depends on whether the conditional that determines if the binding
is active changes frequently or not (or implicitly or not).

By the way, you can also get a behavior similar to the one you suggest
using minor-mode maps (or major-mode maps or text-property maps) where
the menu-item's filter returns nil in some cases (thus deferring to
lower-precedence keymaps).


	Stefan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-26  0:36 ` Richard Stallman
@ 2002-08-26 16:21   ` Stefan Monnier
  2002-08-30 10:27     ` Robert J. Chassell
  0 siblings, 1 reply; 17+ messages in thread
From: Stefan Monnier @ 2002-08-26 16:21 UTC (permalink / raw)
  Cc: storm, emacs-devel

>     One advantage (IMO) is that C-h k C-y will report yank or
>     yank-with-properties depending on the actual function taken if
>     you hit C-y.
> 
> If we use menu-item, what will C-h c say? 

Same thing (it runs the filter).

>       (define-key global-map "\C-y" 'yank-careful)
>       (defun yank-careful (...)
> 	"Reinsert the last stretch of killed text, like `yank'.
>       Contrary to `yank' this function is careful to preserve some important
>       text properties when yanking tables."
> 	...)
> 
>     The advantage is that C-h k C-y doesn't just give you one of the two
>     bindings but a docstring that describes both.
> 
> I think that sometimes this will be better, but sometimes it will be
> better for C-h k to give the doc string for the specific command
> that will be executed.

Agreed.  But in the example he gave I think that a docstring that
describes the range of behavior rather than the specific command is
better, because you can't expect the user to know that the current
string is "special".

I think that whether the docstring should cover all the possible behaviors
or just the specific current one depends on how what the behavior depends on:
if it's very implicit and/or changes often the first is preferable.
This is the case for his example.

OTOH if it's explicit and/or doesn't change often, then the latter is
preferable.  This is the case (and the current behavior) for minor modes.


	Stefan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-26 15:47       ` Stefan Monnier
@ 2002-08-26 19:33         ` Miles Bader
  2002-08-27 19:05           ` Richard Stallman
  2002-08-27 11:23         ` Kim F. Storm
  1 sibling, 1 reply; 17+ messages in thread
From: Miles Bader @ 2002-08-26 19:33 UTC (permalink / raw)
  Cc: Kim F. Storm, David PONCE, emacs-devel

On Mon, Aug 26, 2002 at 11:47:50AM -0400, Stefan Monnier wrote:
> > The point is that you can install a package - like table.el - which is
> > then able to install its own conditional binding on C-y *without*
> > interferring with (or even knowning) the standard binding.
> 
> I don't think that's right.  I don't believe that table wants to override
> C-y sometimes: instead it wants to override `yank' sometimes.
> So what you want to do is to create `yank-careful' and then use
> either the `remap' thingy or substitute-key-definition or something
> like that.

I agree strongly with this; I hate packages that rebind common key-bindings
with their own `equivalent' version -- naturally they fuck up totally if
you've changed the defualt binding, and even when not, such behavior often
seems very fragile.

Much better is some system like fill-paragraph uses where the generic binding
looks for `fill-parapgraph-function' to do the work, which modes can
override.  Of course such a mechanism only works for a limited set of
commands, where it's been established that they are useful to override, and
the variable etc. added -- but I think maybe this is a _good_ thing, not a
problem, and that we just ought to just make it slightly easier to define
such `semantic overrides'.

-Miles
-- 
P.S.  All information contained in the above letter is false,
      for reasons of military security.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-26 15:47       ` Stefan Monnier
  2002-08-26 19:33         ` Miles Bader
@ 2002-08-27 11:23         ` Kim F. Storm
  1 sibling, 0 replies; 17+ messages in thread
From: Kim F. Storm @ 2002-08-27 11:23 UTC (permalink / raw)
  Cc: David PONCE, emacs-devel

"Stefan Monnier" <monnier+gnu/emacs@rum.cs.yale.edu> writes:

> > > You want to have a code.  That's what functions are for.  I think `eval'
> > > should generally be avoided, and `funcall' used instead.
> > > This is especially true if we care about lexical scoping.
> > 
> > I don't quite follow, but I take your word for it :-)
> 
> When you construct a function, the Elisp interpreter/compiler knows that
> it's a piece of code and can do all kinds of things with it (byte-compile
> it, analyze it and put out warnings, build a closure to remember the
> current lexical bindings, ...).
> OTOH, when you build a piece of code to be eval'd, the Elisp
> interpreter/compiler usually has no idea that this is code rather
> than just some kind of list of elements, so it can't do anything
> clever with it.

Ok, but for the uses I can envision for the `cond' binding, there's
probably not much cleverness that can be done with it...

> 
> > > One problem with your change is "what binding do we use when we don't want
> > > to run code?".  The `menu-item' syntax provides a binding (in the example
> > > above it's "my-filter" which is not very useful indeed) for the case
> > > where code should not be evalled (for example in `where-is').
> > 
> > Who said we don't want to run code :-)
> 
> The current code says so.

But the `cond' is equivalent to (and implemented using) `menu-item',
so what's the difference?

I know we don't want to run code in current_minor_maps, but that
isn't involved here AFAICS.

> 
> > > > It will then be quite trivial to enhance `define-key' to handle
> > > > conditional bindings:
> > > 
> > > But is it desirable ?
> > 
> > Don't really know...   It seems like a simple approach to allow
> > packages to hook into "standard bindings".
> 
> How about a set of examples where the current code does not provide
> sufficient flexibility ?  I can come up with plenty of examples
> where we could use your code, but for most/all of them we could
> just as well put the bindings in minor/major-mode-maps or text-property
> keymaps.

Yes, but then the "general functionality" of `menu-item' isn't needed either?

> > The point is that you can install a package - like table.el - which is
> > then able to install its own conditional binding on C-y *without*
> > interferring with (or even knowning) the standard binding.
> 
> I don't think that's right.  I don't believe that table wants to override
> C-y sometimes: instead it wants to override `yank' sometimes.
> So what you want to do is to create `yank-careful' and then use
> either the `remap' thingy or substitute-key-definition or something
> like that.

Yes, I agree with you.  Packages should override commands, not
specific bindings.


> > Then table.el would still be able to install its own conditional
> > binding on C-y.
> 
> Now that's a more interesting example.  But maybe that calls for
> replacing `yank-careful' with a (defadvice yank ...) or something
> like that.  I admit that I don't think either of yank-careful or
> defadvice are quite satisfactory for this case.
> But maybe, using `remap', we could check for an existing `remap'
> binding before adding our own, so that table.el would not defer
> to `yank' but to `yank-careful'.

For that, using the `cond' binding would still be useful I think.
E.g. something like this:

        (define-key global-map [remap yank] 'yank-with-properties
                '(table-p (car kill-ring)))


> 
> > > The advantage is that C-h k C-y doesn't just give you one of the two
> > > bindings but a docstring that describes both.  Of course we could also
> > > improve C-h k to recognize your `cond' construct, etc... but is it
> > > really worth the trouble ?
> > 
> > I didn't think about that, but it would be a nice way to report such
> > "multiple" bindings on a key...
> > 
> > But you may also consider this as a different approach than using a
> > minor-mode-keymap, and in that case, I think C-h k doesn't report all
> > possible bindings for a key -- only the "currently active" binding, so
> > why does `cond' have to behave differently?
> 
> It depends on whether the conditional that determines if the binding
> is active changes frequently or not (or implicitly or not).

Maybe this would be a desired difference between using `cond' and
minor mode bindings.  `cond' bindings report all possible functions,
while minor mode bindings show only the currently active binding.

-- 
Kim F. Storm <storm@cua.dk> http://www.cua.dk

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-26 19:33         ` Miles Bader
@ 2002-08-27 19:05           ` Richard Stallman
  2002-08-27 22:58             ` Kim F. Storm
  2002-08-28  1:00             ` Miles Bader
  0 siblings, 2 replies; 17+ messages in thread
From: Richard Stallman @ 2002-08-27 19:05 UTC (permalink / raw)
  Cc: monnier+gnu/emacs, storm, David.Ponce, emacs-devel

    > I don't think that's right.  I don't believe that table wants to override
    > C-y sometimes: instead it wants to override `yank' sometimes.
    > So what you want to do is to create `yank-careful' and then use
    > either the `remap' thingy or substitute-key-definition or something
    > like that.

I wonder if it is possible for the text property keymap
to remap yank to my-yank, and have this affect bindings
of yank that come from the global map or buffer local map.
Does this work?

    Much better is some system like fill-paragraph uses where the generic binding
    looks for `fill-parapgraph-function' to do the work, which modes can
    override.

It is very useful to set up these hooks in specific places
where we see we need them.  However, we can't expect to provide
these hooks for all the situations where someone wants to override
a certain command for certain text.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-27 19:05           ` Richard Stallman
@ 2002-08-27 22:58             ` Kim F. Storm
  2002-08-28 23:32               ` Richard Stallman
  2002-08-28  1:00             ` Miles Bader
  1 sibling, 1 reply; 17+ messages in thread
From: Kim F. Storm @ 2002-08-27 22:58 UTC (permalink / raw)
  Cc: miles, monnier+gnu/emacs, storm, David.Ponce, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     > I don't think that's right.  I don't believe that table wants to override
>     > C-y sometimes: instead it wants to override `yank' sometimes.
>     > So what you want to do is to create `yank-careful' and then use
>     > either the `remap' thingy or substitute-key-definition or something
>     > like that.
> 
> I wonder if it is possible for the text property keymap
> to remap yank to my-yank, and have this affect bindings
> of yank that come from the global map or buffer local map.
> Does this work?

It should work.

Remapping works by taking the result of the normal key lookup, say
`yank' for C-y and perform a new lookup (in the exact same keymaps)
for the vector [remap yank].  But it will not (and cannot) check the
keymap property of the text _to_be_yanked_.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-27 19:05           ` Richard Stallman
  2002-08-27 22:58             ` Kim F. Storm
@ 2002-08-28  1:00             ` Miles Bader
  2002-08-28  1:22               ` Stefan Monnier
  1 sibling, 1 reply; 17+ messages in thread
From: Miles Bader @ 2002-08-28  1:00 UTC (permalink / raw)
  Cc: monnier+gnu/emacs, storm, David.Ponce, emacs-devel

Richard Stallman <rms@gnu.org> writes:
>     Much better is some system like fill-paragraph uses where the
>     generic binding looks for `fill-parapgraph-function' to do the
>     work, which modes can override.
> 
> It is very useful to set up these hooks in specific places
> where we see we need them.  However, we can't expect to provide
> these hooks for all the situations where someone wants to override
> a certain command for certain text.

Sure; but my point was that there oughta be a better way than just
binding the key.  Maybe there's some halfway point.

-Miles
-- 
"1971 pickup truck; will trade for guns"

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-28  1:00             ` Miles Bader
@ 2002-08-28  1:22               ` Stefan Monnier
  0 siblings, 0 replies; 17+ messages in thread
From: Stefan Monnier @ 2002-08-28  1:22 UTC (permalink / raw)
  Cc: rms, monnier+gnu/emacs, storm, David.Ponce, emacs-devel

> Richard Stallman <rms@gnu.org> writes:
> >     Much better is some system like fill-paragraph uses where the
> >     generic binding looks for `fill-parapgraph-function' to do the
> >     work, which modes can override.
> > 
> > It is very useful to set up these hooks in specific places
> > where we see we need them.  However, we can't expect to provide
> > these hooks for all the situations where someone wants to override
> > a certain command for certain text.
> 
> Sure; but my point was that there oughta be a better way than just
> binding the key.  Maybe there's some halfway point.

There's always defadvice.
And there's the new `remap' facility.


	Stefan

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-27 22:58             ` Kim F. Storm
@ 2002-08-28 23:32               ` Richard Stallman
  2002-08-29  8:54                 ` Kim F. Storm
  0 siblings, 1 reply; 17+ messages in thread
From: Richard Stallman @ 2002-08-28 23:32 UTC (permalink / raw)
  Cc: miles, monnier+gnu/emacs, storm, David.Ponce, emacs-devel

    Remapping works by taking the result of the normal key lookup, say
    `yank' for C-y and perform a new lookup (in the exact same keymaps)
    for the vector [remap yank].  But it will not (and cannot) check the
    keymap property of the text _to_be_yanked_.

Nothing in Emacs will check the keymap property of the text to be
yanked.  Conditional key bindings wouldn't do that either.  So how
does this relate?

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-28 23:32               ` Richard Stallman
@ 2002-08-29  8:54                 ` Kim F. Storm
  0 siblings, 0 replies; 17+ messages in thread
From: Kim F. Storm @ 2002-08-29  8:54 UTC (permalink / raw)
  Cc: storm, miles, monnier+gnu/emacs, David.Ponce, emacs-devel

Richard Stallman <rms@gnu.org> writes:

>     Remapping works by taking the result of the normal key lookup, say
>     `yank' for C-y and perform a new lookup (in the exact same keymaps)
>     for the vector [remap yank].  But it will not (and cannot) check the
>     keymap property of the text _to_be_yanked_.
> 
> Nothing in Emacs will check the keymap property of the text to be
> yanked.  Conditional key bindings wouldn't do that either.  So how
> does this relate?

In the context of discussing how to make C-y/yank behave differently
depending on the text it is going to yank, checking for a [remap yank]
keymap property in the to_be_yanked text might be a (far-fetched)
possibility.

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: Suggestion: Simple way to make conditional key bindings.
  2002-08-26 16:21   ` Stefan Monnier
@ 2002-08-30 10:27     ` Robert J. Chassell
  0 siblings, 0 replies; 17+ messages in thread
From: Robert J. Chassell @ 2002-08-30 10:27 UTC (permalink / raw)


   >     ... C-h k C-y will report yank or yank-with-properties
   >     depending on the actual function taken if you hit C-y. ....

   > .... sometimes it will be better for C-h k to give the doc string
   > for the specific command that will be executed.

   Agreed.  But in the example he gave I think that a docstring that
   describes the range of behavior rather than the specific command is
   better, because you can't expect the user to know that the current
   string is "special".

Yes:  the user may not know or remember the range.  (At the moment,
for example, I am in the middle of a long airplane flight and too
exhausted to remember much, even though some of the time I am quite
good.)

At the same time, for this sort of command, which operates differently
in different contexts, the docstring should describe what the command
will do specifically in this situation.

-- 
    Robert J. Chassell            bob@rattlesnake.com  bob@gnu.org
    Rattlesnake Enterprises       http://www.rattlesnake.com
    Free Software Foundation      http://www.gnu.org   GnuPG Key ID: 004B4AC8

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2002-08-30 10:27 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <3D49FF140074EFAE@mel-rta7.wanadoo.fr>
2002-08-23 13:16 ` Suggestion: Simple way to make conditional key bindings Kim F. Storm
2002-08-23 17:22   ` Stefan Monnier
2002-08-25 23:33     ` Kim F. Storm
2002-08-26 15:47       ` Stefan Monnier
2002-08-26 19:33         ` Miles Bader
2002-08-27 19:05           ` Richard Stallman
2002-08-27 22:58             ` Kim F. Storm
2002-08-28 23:32               ` Richard Stallman
2002-08-29  8:54                 ` Kim F. Storm
2002-08-28  1:00             ` Miles Bader
2002-08-28  1:22               ` Stefan Monnier
2002-08-27 11:23         ` Kim F. Storm
2002-08-23 12:52 David PONCE
  -- strict thread matches above, loose matches on Subject: below --
2002-08-23 12:05 Kim F. Storm
2002-08-26  0:36 ` Richard Stallman
2002-08-26 16:21   ` Stefan Monnier
2002-08-30 10:27     ` Robert J. Chassell

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).