emacs-devel
[Top][All Lists]
Advanced

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

Re: Get a command by its keybinding and also respecting key translation


From: Tassilo Horn
Subject: Re: Get a command by its keybinding and also respecting key translation
Date: Wed, 15 Dec 2010 16:27:03 +0100
User-agent: KMail/1.13.5 (Linux/2.6.37-rc5+; KDE/4.5.4; x86_64; ; )

On Wednesday 15 December 2010 09:21:21 Tassilo Horn wrote:

Hi again!

> This is cool, but sadly not equivalent, because I cannot add multiple
> binding for one key in the same keymap.  That was the whole intention
>
> In my approach with multiple TAB bindings in one keymap, the last one
> defined was the real binding, but if its predicate didn't match, it
> delegated to the former binding of TAB (which it had stolen), and if
> all predicates of all context keys failed, it would call the original
> command.
> 
> So do I go to implement that behavior in a more standard way?

Ok, now I've revamped my macro according to your example with some
changes.  A dispatching form has to be provided that returns the
function to use, or nil if the original binding should be triggered.
Additionally, I let-bind a variable default-command to that original
binding in order to make it possible to trigger context sensitive
behavior only after hitting a key twice.

What do you think of that?

--8<---------------cut here---------------start------------->8---
(defmacro define-context-key (keymap key dispatch)
  "Define KEY in KEYMAP to execute according to DISPATCH.

DISPATCH is a form that is evaluated and should return the
command to be executed.

If DISPATCH returns nil, then the command normally bound to KEY
will be executed.

DISPATCH can access a dynamically set variable `default-command',
which contains the command that would be executed, if DISPATCH
returns nil.  This makes it possible to make DISPATCH return some
command only if a user wants to trigger it twice in a row.

Example:

  (define-context-key hs-minor-mode-map
     (kbd \"TAB\")
     (cond
      ((and (not (hs-already-hidden-p))
            (eq last-command default-command))
       'hs-hide-block)
      ((hs-already-hidden-p)
       'hs-show-block)))

This will make TAB show a hidden block.  If the block is shown,
then the first TAB will act as usual (e.g. indent the code), but
the second TAB will hide the block."
  `(define-key ,keymap ,key
     (quote
      (menu-item "context-key" ignore
                 :filter (lambda (&optional ignored)
                           (let ((default-command (key-binding ,key t)))
                             ,dispatch))))))
--8<---------------cut here---------------end--------------->8---

Bye,
Tassilo



reply via email to

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