unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* substitute-key-definition vs. define-key MAP [remap ...]
@ 2010-07-15  8:25 Teemu Likonen
  2010-07-22 22:36 ` Stefan Monnier
  0 siblings, 1 reply; 14+ messages in thread
From: Teemu Likonen @ 2010-07-15  8:25 UTC (permalink / raw)
  To: emacs-devel

Some Emacs modes use substitute-key-definition function to redirect some
global key-commands to mode-specific commands. My view is that using
define-key and its [remap ...] functionality would be better.

The problem I'm seeing is that global keys defined in a global minor
mode don't work with substitute-key-definition. Here's an example, first
a working one: cc-mode has this (in cc-mode.el):

    (substitute-key-definition 'indent-new-comment-line
                               'c-indent-new-comment-line
                               c-mode-base-map global-map)

In default global-map M-j runs indent-new-comment-line. Now, let's say
that I have this in my .emacs file:

    (global-set-key [f7] 'indent-new-comment-line)

This works nicely with cc-mode: f7 will run c-indent-new-comment-line
instead of indent-new-comment-line.

But if I don't redefine f7 key in the global map but use a global minor
mode instead to shadow some of the global map (like the command
indent-new-comment-line) then that binding won't be substituted in
cc-mode. In other words, when my global minor mode is activated, the key
for indent-new-comment-line will just run that and not
c-indent-new-comment-line in cc-mode. If you want to test that here's a
small minor mode for you:

    (defvar my-global-minor-mode-map
      (let ((map (make-sparse-keymap)))
        (define-key map [f7] 'indent-new-comment-line)
        map))

    (define-minor-mode my-global-minor-mode
      "\\{my-global-minor-mode-map}"
      :global t :lighter " my-mode" :keymap my-global-minor-mode-map)

All this would work nicely if cc-mode used [remap ...]:

    (define-key c-mode-base-map
      [remap indent-new-comment-line]
      'c-indent-new-comment-line)

So, am I right in saying that using substitute-key-definition on global
map directly is a bad practice? I guess the question is whether you/we
want to let user create custom global bindings through a global minor
mode. It would be nice and convenient because global minor modes can be
turned on and off. User may want to have different minor modes for
redefining the basic global keys for different editing tasks.



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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-15  8:25 substitute-key-definition vs. define-key MAP [remap ...] Teemu Likonen
@ 2010-07-22 22:36 ` Stefan Monnier
  2010-07-23  3:50   ` Stephen J. Turnbull
  0 siblings, 1 reply; 14+ messages in thread
From: Stefan Monnier @ 2010-07-22 22:36 UTC (permalink / raw)
  To: Teemu Likonen; +Cc: emacs-devel

> So, am I right in saying that using substitute-key-definition on global
> map directly is a bad practice?

Yes and no.  Part of the reason why it exists is because that code was
written before remap was available.  Another part is because I'm not
sure remap is available in XEmacs, so packages who want to work in
XEmacs may prefer not to use it.

Finally, in some cases, using remap is not the right answer either
because remap not only replaces the command at its "usual" key-bindings,
but at all its key-bindings, which means that the user has no way to
access the original command other than via M-x (she can't make her own
key-binding for it, for instance).  So remap can only be used when the
remapped command really makes the original command undesirable.


        Stefan



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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-22 22:36 ` Stefan Monnier
@ 2010-07-23  3:50   ` Stephen J. Turnbull
  2010-07-23  9:26     ` Stefan Monnier
  0 siblings, 1 reply; 14+ messages in thread
From: Stephen J. Turnbull @ 2010-07-23  3:50 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Teemu Likonen, emacs-devel

Stefan Monnier writes:

 > > So, am I right in saying that using substitute-key-definition on global
 > > map directly is a bad practice?
 > 
 > Yes and no.  Part of the reason why it exists is because that code was
 > written before remap was available.  Another part is because I'm not
 > sure remap is available in XEmacs, so packages who want to work in
 > XEmacs may prefer not to use it.

It's not available in XEmacs.

I haven't thought carefully about it, but my initial reaction is to
oppose introducing it.  It adds a lot of complexity (an additional
layer of indirection), and like `substitute-key-definition', it
postpones the real solution to issues that create demand for these
features: rewrite the function so that it can be configured by users,
modes, etc.

 > Finally, in some cases, using remap is not the right answer either
 > because remap not only replaces the command at its "usual" key-bindings,
 > but at all its key-bindings,

If I understand you correctly, that won't get into XEmacs any time
soon.  Do you really mean that `define-key' is allowed to effectively
change the command binding of a symbol globally, so that its function
definition is ignored in the context of interpreting keystrokes?  Ie,
`define-key' now turns Emacs into what is effectively a LISP-3?





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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-23  3:50   ` Stephen J. Turnbull
@ 2010-07-23  9:26     ` Stefan Monnier
  2010-07-23  9:32       ` Miles Bader
  2010-07-23 10:03       ` David Kastrup
  0 siblings, 2 replies; 14+ messages in thread
From: Stefan Monnier @ 2010-07-23  9:26 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: Teemu Likonen, emacs-devel

> If I understand you correctly, that won't get into XEmacs any time
> soon.  Do you really mean that `define-key' is allowed to effectively
> change the command binding of a symbol globally, so that its function
> definition is ignored in the context of interpreting keystrokes?  Ie,
> `define-key' now turns Emacs into what is effectively a LISP-3?

I don't know what "ignored in the context of interpreting keystrokes"
means, nor what LISP-3 means.

The `remap' thingy operates at the level of `key-binding'.  I.e. after
the command loop reads a key-sequence, it looks it up in the keymaps to
turn the key-sequence into a command, and then it looks this up in the
`remap' sub-keymap(s) to see if it got remapped.

So if you want to bind the original command to a key, you have to trick
the remapping by using another command name, e.g.:

  (defalias 'new-name-for-old-command 'old-remapped-command)
  (define-key MAP [KEYS] 'new-name-for-old-command)

since the remapping will apply to `old-remapped-command' but not to
`new-name-for-old-command'.  There are other ways, of course, such as:

  (define-key MAP [KEYS]
    (lambda () (interactive) (call-interactively 'old-remapped-command)))


-- Stefan



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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-23  9:26     ` Stefan Monnier
@ 2010-07-23  9:32       ` Miles Bader
  2010-07-24  7:08         ` Stephen J. Turnbull
  2010-07-23 10:03       ` David Kastrup
  1 sibling, 1 reply; 14+ messages in thread
From: Miles Bader @ 2010-07-23  9:32 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Stephen J. Turnbull, Teemu Likonen, emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:
> The `remap' thingy operates at the level of `key-binding'.  I.e. after
> the command loop reads a key-sequence, it looks it up in the keymaps to
> turn the key-sequence into a command, and then it looks this up in the
> `remap' sub-keymap(s) to see if it got remapped.

And it's _extremely_ handy for some uses... e.g., one of my favorite
tricks is little minor-modes that bind [remap self-insert-command]...

E.g.:

   ;;; caps-lock-mode, Miles Bader <miles@gnu.org>

   (defvar caps-lock-mode-map
     (let ((map (make-sparse-keymap)))
       (define-key map [remap self-insert-command] 'self-insert-upcased)
       map))

   (define-minor-mode caps-lock-mode
     "When enabled, convert all self-inserting characters to uppercase."
     :lighter " CapsLock")

   (defun self-insert-upcased (arg)
     (interactive "p")
     (setq last-command-char (upcase last-command-char))
     (self-insert-command arg))

-miles

-- 
Politics, n. A strife of interests masquerading as a contest of
principles. The conduct of public affairs for private advantage.



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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-23  9:26     ` Stefan Monnier
  2010-07-23  9:32       ` Miles Bader
@ 2010-07-23 10:03       ` David Kastrup
  2010-07-24  6:27         ` Stephen J. Turnbull
  1 sibling, 1 reply; 14+ messages in thread
From: David Kastrup @ 2010-07-23 10:03 UTC (permalink / raw)
  To: emacs-devel

Stefan Monnier <monnier@IRO.UMontreal.CA> writes:

>> If I understand you correctly, that won't get into XEmacs any time
>> soon.  Do you really mean that `define-key' is allowed to effectively
>> change the command binding of a symbol globally, so that its function
>> definition is ignored in the context of interpreting keystrokes?  Ie,
>> `define-key' now turns Emacs into what is effectively a LISP-3?
>
> I don't know what "ignored in the context of interpreting keystrokes"
> means, nor what LISP-3 means.

I think a LISP-2 has both function and value cells associated with a
symbol (never mind print name and property list in that kind of
accounting), making Scheme a LISP-1.

-- 
David Kastrup




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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-23 10:03       ` David Kastrup
@ 2010-07-24  6:27         ` Stephen J. Turnbull
  0 siblings, 0 replies; 14+ messages in thread
From: Stephen J. Turnbull @ 2010-07-24  6:27 UTC (permalink / raw)
  To: David Kastrup; +Cc: emacs-devel

David Kastrup writes:

 > I think a LISP-2 has both function and value cells associated with a
 > symbol (never mind print name and property list in that kind of
 > accounting), making Scheme a LISP-1.

The point is that there is a syntactic distinction, not that it
happens to be implemented as cells in the symbol structure.  For
example, some simple LISPs have only one cell, for the property list,
and all of the features you mention are implemented as properties.





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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-23  9:32       ` Miles Bader
@ 2010-07-24  7:08         ` Stephen J. Turnbull
  2010-07-24  8:19           ` David Kastrup
  2010-07-24  9:33           ` Miles Bader
  0 siblings, 2 replies; 14+ messages in thread
From: Stephen J. Turnbull @ 2010-07-24  7:08 UTC (permalink / raw)
  To: Miles Bader; +Cc: Teemu Likonen, Stefan Monnier, emacs-devel

Miles Bader writes:

 > And it's _extremely_ handy for some uses... e.g., one of my favorite
 > tricks is little minor-modes that bind [remap self-insert-command]...

It's a handy hack, I'm sure.  I think there are better ways to achieve
the same end, that's all.




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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-24  7:08         ` Stephen J. Turnbull
@ 2010-07-24  8:19           ` David Kastrup
  2010-07-24  9:33           ` Miles Bader
  1 sibling, 0 replies; 14+ messages in thread
From: David Kastrup @ 2010-07-24  8:19 UTC (permalink / raw)
  To: emacs-devel

"Stephen J. Turnbull" <stephen@xemacs.org> writes:

> Miles Bader writes:
>
>  > And it's _extremely_ handy for some uses... e.g., one of my favorite
>  > tricks is little minor-modes that bind [remap self-insert-command]...
>
> It's a handy hack, I'm sure.  I think there are better ways to achieve
> the same end, that's all.

Yes and no.  Within Emacs, menus, toolbars, and other stuff are all
routed through keymaps, making the hierarchic collection of the various
keymaps effectively another scoping tool.  Being able to solve the
remapping within that hierarchy rather than separately certainly makes
sense.

XEmacs, in contrast, has the separate concept of locale specifiers for
that sort of scoping.  So within the XEmacs framework, there might be
less ad-hoc looking ways to implement similar goals.

Personally, I find the keymap recycling of Emacs a hack with rather
straightforward semantics, certainly worth not having to worry about
another abstraction level that gets in the way even if you are only
concerned with keymaps and nothing else.

-- 
David Kastrup




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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-24  7:08         ` Stephen J. Turnbull
  2010-07-24  8:19           ` David Kastrup
@ 2010-07-24  9:33           ` Miles Bader
  2010-07-24 14:25             ` Stephen J. Turnbull
  1 sibling, 1 reply; 14+ messages in thread
From: Miles Bader @ 2010-07-24  9:33 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: Teemu Likonen, Stefan Monnier, emacs-devel

"Stephen J. Turnbull" <stephen@xemacs.org> writes:
>  > And it's _extremely_ handy for some uses... e.g., one of my favorite
>  > tricks is little minor-modes that bind [remap self-insert-command]...
>
> It's a handy hack, I'm sure.  I think there are better ways to achieve
> the same end, that's all.

For instance?  Solutions as adding hooks/functions for to allow
mode-specific semantics for standard commands
(e.g. `fill-paragraph-function') are better for those cases, I think,
but they have far higher cost (they must be added by the emacs
developer), and are not really so nice for minor modes -- IOW, it
doesn't really achieve the same thing.

-Miles

-- 
Once, adj. Enough.



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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-24  9:33           ` Miles Bader
@ 2010-07-24 14:25             ` Stephen J. Turnbull
  2010-07-25  3:21               ` Miles Bader
  0 siblings, 1 reply; 14+ messages in thread
From: Stephen J. Turnbull @ 2010-07-24 14:25 UTC (permalink / raw)
  To: Miles Bader; +Cc: Teemu Likonen, Stefan Monnier, emacs-devel

Miles Bader writes:
 > "Stephen J. Turnbull" <stephen@xemacs.org> writes:
 > >  > And it's _extremely_ handy for some uses... e.g., one of my favorite
 > >  > tricks is little minor-modes that bind [remap self-insert-command]...
 > >
 > > It's a handy hack, I'm sure.  I think there are better ways to achieve
 > > the same end, that's all.
 > 
 > For instance?  Solutions as adding hooks/functions for to allow
 > mode-specific semantics for standard commands
 > (e.g. `fill-paragraph-function') are better for those cases, I think,
 > but they have far higher cost (they must be added by the emacs
 > developer), and are not really so nice for minor modes -- IOW, it
 > doesn't really achieve the same thing.

Use of defun is not restricted to emacs developers (and you will often
need to use it with [remap] anyway).

For handy hacks, I really don't see what's so horrible about

(define-minor-mode caps-lock-mode
  "Only useful with a Happy Hacker keyboard."
  :lighter "CapsLock")
(defadvice self-insert-command (before caps-lock-mode activate)
  "Make self-insert-command respect caps-lock-mode."
  (when caps-lock-mode
    (set last-command-key (upcase last-command-key))))

and I certainly don't think that concealing a limited advice
capability in the keymap lookup process is any better than advice
itself.




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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-24 14:25             ` Stephen J. Turnbull
@ 2010-07-25  3:21               ` Miles Bader
  2010-07-25 10:19                 ` Stephen J. Turnbull
  0 siblings, 1 reply; 14+ messages in thread
From: Miles Bader @ 2010-07-25  3:21 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: Teemu Likonen, Stefan Monnier, emacs-devel

"Stephen J. Turnbull" <stephen@xemacs.org> writes:
> For handy hacks, I really don't see what's so horrible about
> (defadvice self-insert-command (before caps-lock-mode activate)

So multiply that times 20 such little modes, and note that
self-insert-command is probably the most heavily-used command in
emacs...

> and I certainly don't think that concealing a limited advice
> capability in the keymap lookup process is any better than advice
> itself.

It's far better, because it follows the normal scoping rules of keymaps
(which is even more important in the case of minor mode maps), allowing
such overrides to be very narrowly targetted.  defadvice is a clumsy and
blunt tool by comparison.

[Yeah, I know, xemacs doesn't have [remap], and I don't expect you to
sing its charms....]

-Miles

-- 
Youth, n. The Period of Possibility, when Archimedes finds a fulcrum,
Cassandra has a following and seven cities compete for the honor of endowing a
living Homer.



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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-25  3:21               ` Miles Bader
@ 2010-07-25 10:19                 ` Stephen J. Turnbull
  2010-07-25 13:43                   ` Miles Bader
  0 siblings, 1 reply; 14+ messages in thread
From: Stephen J. Turnbull @ 2010-07-25 10:19 UTC (permalink / raw)
  To: Miles Bader; +Cc: Teemu Likonen, Stefan Monnier, emacs-devel

Miles Bader writes:

 > It's far better, because it follows the normal scoping rules of
 > keymaps

OK, but that's not what I understood from Stefan's description.  He
said that remapping would affect *all* uses of the command as a
binding, requiring either invocation via M-x or renaming the command.




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

* Re: substitute-key-definition vs. define-key MAP [remap ...]
  2010-07-25 10:19                 ` Stephen J. Turnbull
@ 2010-07-25 13:43                   ` Miles Bader
  0 siblings, 0 replies; 14+ messages in thread
From: Miles Bader @ 2010-07-25 13:43 UTC (permalink / raw)
  To: Stephen J. Turnbull; +Cc: Teemu Likonen, Stefan Monnier, emacs-devel

"Stephen J. Turnbull" <stephen@xemacs.org> writes:
>  > It's far better, because it follows the normal scoping rules of
>  > keymaps
>
> OK, but that's not what I understood from Stefan's description.  He
> said that remapping would affect *all* uses of the command as a
> binding, requiring either invocation via M-x or renaming the command.

It affects all uses _where the [remap ...] key-entry is visible (in the
same way a normal binding is visible)_.

So in my example, when caps-lock-mode is turned on, a small [remap]
binding becomes visible via minor-mode-map-alist, and thus affects
keystrokes in that buffer (until you turn off the minor-mode, which
implicitly disables its keymap).

[I have no idea what the implementation is like, but the above is the
basic idea.]

-Miles

-- 
We are all lying in the gutter, but some of us are looking at the stars.
-Oscar Wilde



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

end of thread, other threads:[~2010-07-25 13:43 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-07-15  8:25 substitute-key-definition vs. define-key MAP [remap ...] Teemu Likonen
2010-07-22 22:36 ` Stefan Monnier
2010-07-23  3:50   ` Stephen J. Turnbull
2010-07-23  9:26     ` Stefan Monnier
2010-07-23  9:32       ` Miles Bader
2010-07-24  7:08         ` Stephen J. Turnbull
2010-07-24  8:19           ` David Kastrup
2010-07-24  9:33           ` Miles Bader
2010-07-24 14:25             ` Stephen J. Turnbull
2010-07-25  3:21               ` Miles Bader
2010-07-25 10:19                 ` Stephen J. Turnbull
2010-07-25 13:43                   ` Miles Bader
2010-07-23 10:03       ` David Kastrup
2010-07-24  6:27         ` Stephen J. Turnbull

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