unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* A simple implementation of context-sensitive keys
@ 2008-09-10  7:17 Tassilo Horn
  2008-09-10 10:36 ` Lennart Borgman (gmail)
                   ` (2 more replies)
  0 siblings, 3 replies; 36+ messages in thread
From: Tassilo Horn @ 2008-09-10  7:17 UTC (permalink / raw)
  To: emacs-devel

Hi all,

to get the full power out of emacs, I use quite a lot of different minor
modes with a ton of home-brewn functions.  To make them quickly
accessible, I've bound them to some key.  But "good" keys are rare, and
so I started writing special dispatching commands which DTRT dependend
on the context they're used in.  But that's quite cumbersome, because
ideally you have to recognize each command which would normally be bound
to the key, too.

So I've come up with this macro, which creates such a dispatching
command automagically.  If none of the context predicates match, the
default command bound to the key will be executed.

--8<---------------cut here---------------start------------->8---
(defmacro define-context-key (mode key preds-funs)
  "Bind KEY to an anonymous dispatching command in MODE.
PREDS-FUNS is an alist with elements of the form

    (PREDICATE . FUNCTION).

The dispatching command calls the first PREDICATE, and if that
returns non-nil, it'll call the associated FUNCTION.  If the
first PREDICATE returns nil, the next one will be tested and so
on.

If no PREDICATE matches and KEY is normally bound in MODE, the
corresponding command will be executed.

If KEY isn't normally bound in MODE, MODE will be disabled
temporally (to prevent an infinite recursion) and the function
which is then bound to KEY will be called."
  (let* ((keymap        (intern (concat (symbol-name mode) "-map")))
         (default-fun   (lookup-key (symbol-value keymap) (eval key)))
         (block-name    (gensym))
         (iter-var-name (gensym)))
    `(define-key ,keymap ,key
       (lambda ()	
         (interactive)
         (block ,block-name
           (dolist (,iter-var-name (quote ,preds-funs))
             (when (funcall (car ,iter-var-name))
               (call-interactively (cdr ,iter-var-name))
               (return-from ,block-name)))
           (if (quote ,default-fun)
               (call-interactively (quote ,default-fun))
             (let (,mode)
               (call-interactively (key-binding ,key)))))))))
--8<---------------cut here---------------end--------------->8---

Here's a usage example: I'm used to structure source code files with
`outline-minor-mode'.  But the default keys of this mode are too hard to
type and remember.  (I only use `outline-toggle-children' anyway.)  So
instead of binding that command to some other key, I use my macro to
make TAB context-sensitive:

--8<---------------cut here---------------start------------->8---
(defun outline-context-p ()
  (save-excursion
    (goto-char (line-beginning-position))
    (looking-at outline-regexp)))

(define-context-key outline-minor-mode
  (kbd "TAB")
  ((outline-context-p . outline-toggle-children)))
--8<---------------cut here---------------end--------------->8---
 
`outline-context-p' returns non-nil when point is on a outline heading.
Now the TAB key calls `outline-toggle-children' if I'm on such a
headline.  If not, `outline-minor-mode' will be disabled temporally
(cause `outline-minor-mode' doesn't define a command bound to TAB on its
own) and the next mode will get it's chance, i.e. the code will be
indented according to mode.

What do you think of it?

I use it for some hours now, so it's only very briefly tested, but it
seems to DTRT.  Of course, this cannot go into the emacs core because it
uses `cl' capabilities, but IMO a feature like that could be of great
benefit to users.

BTW: The idea and the mechanism how to get the command that would have
been executed normally is stolen from Carsten Dominik's fabulous
org-mode package (or more accurately `orgstruct-mode').  And there're
other packages (yasnippet comes into mind), which implement such a
feature on their own, too.  So a more general concept of context
sensitive keys seems sensible.

Bye,
Tassilo




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

* Re: A simple implementation of context-sensitive keys
  2008-09-10  7:17 A simple implementation of context-sensitive keys Tassilo Horn
@ 2008-09-10 10:36 ` Lennart Borgman (gmail)
  2008-09-10 10:57   ` Tassilo Horn
  2008-09-10 14:14 ` Sean O'Rourke
  2008-09-10 17:49 ` Stefan Monnier
  2 siblings, 1 reply; 36+ messages in thread
From: Lennart Borgman (gmail) @ 2008-09-10 10:36 UTC (permalink / raw)
  To: emacs-devel, Tassilo Horn

Tassilo Horn wrote:
> Hi all,
> 
> to get the full power out of emacs, I use quite a lot of different minor
> modes with a ton of home-brewn functions.  To make them quickly
> accessible, I've bound them to some key.  But "good" keys are rare, and
> so I started writing special dispatching commands which DTRT dependend
> on the context they're used in.  But that's quite cumbersome, because
> ideally you have to recognize each command which would normally be bound
> to the key, too.
> 
> So I've come up with this macro, which creates such a dispatching
> command automagically.  If none of the context predicates match, the
> default command bound to the key will be executed.
> 
> --8<---------------cut here---------------start------------->8---
> (defmacro define-context-key (mode key preds-funs)
>   "Bind KEY to an anonymous dispatching command in MODE.
> PREDS-FUNS is an alist with elements of the form


Hi Tassilo

I think there are a number of packages out there doing quite similar
things: smart-tab, tabkey2, hippi-expand.

Those are all focused on completion, but that is more a conceptual focus
(which I think is good). By default they bind the Tab key (which you
also did in your example). Maybe it would be good to generalize that as
you did here.

In tabkey2.el (did you notice it when I sent it to this list?) I have
tried to write the supporting functions needed to make the key bindings
transparent to the user. You are welcome to contribute to it if you want
too. The latest version is always in nXhtml on Launchpad.

BTW Yasnippet is a kind of completion function.




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

* Re: A simple implementation of context-sensitive keys
  2008-09-10 10:36 ` Lennart Borgman (gmail)
@ 2008-09-10 10:57   ` Tassilo Horn
  2008-09-10 16:43     ` Ted Zlatanov
  0 siblings, 1 reply; 36+ messages in thread
From: Tassilo Horn @ 2008-09-10 10:57 UTC (permalink / raw)
  To: emacs-devel; +Cc: Lennart Borgman (gmail)

"Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:

Hi Lennart,

> I think there are a number of packages out there doing quite similar
> things: smart-tab, tabkey2, hippi-expand.

I know, and I think it's bad that each and every package tries to
reinvent the wheel, so I propose a more general approach.

Here's an improved version which gets rid of the cl dependency.  IMO
this could be added to emacs.

--8<---------------cut here---------------start------------->8---
(defmacro define-context-key (mode key predicate function)
  "Bind KEY in MODE's map to a command which calls FUNCTION if PREDICATE is non-nil.

If PREDICATE doesn't match and KEY is normally bound in MODE, the
corresponding default command will be executed.

If KEY isn't normally bound in MODE, MODE will be disabled
temporally (to prevent an infinite recursion) and the function
which is then bound to KEY will be called."
  (let* ((keymap        (intern (concat (symbol-name mode) "-map")))
         (default-fun   (lookup-key (symbol-value keymap) (eval key))))
    `(define-key ,keymap ,key
       (lambda ()	
       (interactive)
       (if (funcall (quote ,predicate))
           (call-interactively (quote ,function))
         (if (quote ,default-fun)
             (call-interactively (quote ,default-fun))
           (let (,mode)
             (call-interactively (key-binding ,key)))))))))
--8<---------------cut here---------------end--------------->8---

Multiple calls operate cumulative, so something like this works
beautiful.

--8<---------------cut here---------------start------------->8---
(defun outline-context-p ()
  (save-excursion
    (goto-char (line-beginning-position))
    (looking-at outline-regexp)))

(define-context-key outline-minor-mode
  (kbd "TAB") outline-context-p outline-toggle-children)
(define-context-key outline-minor-mode
  (kbd "TAB") eolp self-insert-command)
--8<---------------cut here---------------end--------------->8---

Bye,
Tassilo
-- 
One time, at band camp, Chuck Norris ate a percussionist. 




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

* Re: A simple implementation of context-sensitive keys
  2008-09-10  7:17 A simple implementation of context-sensitive keys Tassilo Horn
  2008-09-10 10:36 ` Lennart Borgman (gmail)
@ 2008-09-10 14:14 ` Sean O'Rourke
  2008-09-10 14:48   ` Miles Bader
  2008-09-10 17:49 ` Stefan Monnier
  2 siblings, 1 reply; 36+ messages in thread
From: Sean O'Rourke @ 2008-09-10 14:14 UTC (permalink / raw)
  To: emacs-devel

Tassilo Horn <tassilo@member.fsf.org> writes:
> But "good" keys are rare, and so I started writing special
> dispatching commands which DTRT dependend on the context
> they're used in.

TextMate for Mac OS has a similar way of defining key bindings:
basically, a major mode labels regions of a buffer's text, and
keys can be bound to functions only within regions with certain
labels.  It's like font-lock for keys (IIRC, TextMate's
fontification uses these same labels).  I think it's a great
idea, and would like to see some general mechanism for doing it
included in Emacs.

Sean





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

* Re: A simple implementation of context-sensitive keys
  2008-09-10 14:14 ` Sean O'Rourke
@ 2008-09-10 14:48   ` Miles Bader
  2008-09-10 14:53     ` Juanma Barranquero
  2008-09-11  7:35     ` Tassilo Horn
  0 siblings, 2 replies; 36+ messages in thread
From: Miles Bader @ 2008-09-10 14:48 UTC (permalink / raw)
  To: Sean O'Rourke; +Cc: emacs-devel

Sean O'Rourke <seano@cs.ucla.edu> writes:
> TextMate for Mac OS has a similar way of defining key bindings:
> basically, a major mode labels regions of a buffer's text, and
> keys can be bound to functions only within regions with certain
> labels.  It's like font-lock for keys (IIRC, TextMate's
> fontification uses these same labels).  I think it's a great
> idea, and would like to see some general mechanism for doing it
> included in Emacs.

Emacs does have keymap properties...

-Miles

-- 
Next to fried food, the South has suffered most from oratory.
  			-- Walter Hines Page




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

* Re: A simple implementation of context-sensitive keys
  2008-09-10 14:48   ` Miles Bader
@ 2008-09-10 14:53     ` Juanma Barranquero
  2008-09-10 15:17       ` Sean O'Rourke
  2008-09-11  7:35     ` Tassilo Horn
  1 sibling, 1 reply; 36+ messages in thread
From: Juanma Barranquero @ 2008-09-10 14:53 UTC (permalink / raw)
  To: Miles Bader; +Cc: Sean O'Rourke, emacs-devel

On Wed, Sep 10, 2008 at 16:48, Miles Bader <miles@gnu.org> wrote:

> Emacs does have keymap properties...

What are keymap properties? Where are they documented, and under which name?

 Juanma




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

* Re: A simple implementation of context-sensitive keys
  2008-09-10 14:53     ` Juanma Barranquero
@ 2008-09-10 15:17       ` Sean O'Rourke
  2008-09-10 15:32         ` Juanma Barranquero
  0 siblings, 1 reply; 36+ messages in thread
From: Sean O'Rourke @ 2008-09-10 15:17 UTC (permalink / raw)
  To: emacs-devel

"Juanma Barranquero" <lekktu@gmail.com> writes:

> On Wed, Sep 10, 2008 at 16:48, Miles Bader <miles@gnu.org> wrote:
>
>> Emacs does have keymap properties...
>
> What are keymap properties? Where are they documented, and
> under which name?

My guess is that this is the text property used by e.g.
"customize" to create buttons and links.  I would like something
similar to `define-key' that takes a "context" argument.  Is
whatever defcustom uses this simple?

Sean





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

* Re: A simple implementation of context-sensitive keys
  2008-09-10 15:17       ` Sean O'Rourke
@ 2008-09-10 15:32         ` Juanma Barranquero
  0 siblings, 0 replies; 36+ messages in thread
From: Juanma Barranquero @ 2008-09-10 15:32 UTC (permalink / raw)
  To: Sean O'Rourke; +Cc: emacs-devel

On Wed, Sep 10, 2008 at 17:17, Sean O'Rourke <seano@cs.ucla.edu> wrote:

> My guess is that this is the text property used by e.g.
> "customize" to create buttons and links.

Ah. Properties that contain (point to) keymaps. I was misreading that
as "properties of the keymaps", as in "symbol properties" and "text
properties" :)

 Juanma




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

* Re: A simple implementation of context-sensitive keys
  2008-09-10 10:57   ` Tassilo Horn
@ 2008-09-10 16:43     ` Ted Zlatanov
  0 siblings, 0 replies; 36+ messages in thread
From: Ted Zlatanov @ 2008-09-10 16:43 UTC (permalink / raw)
  To: emacs-devel

On Wed, 10 Sep 2008 12:57:56 +0200 Tassilo Horn <tassilo@member.fsf.org> wrote: 

TH> (defmacro define-context-key (mode key predicate function)
TH>   "Bind KEY in MODE's map to a command which calls FUNCTION if PREDICATE is non-nil.

TH> If PREDICATE doesn't match and KEY is normally bound in MODE, the
TH> corresponding default command will be executed.

TH> If KEY isn't normally bound in MODE, MODE will be disabled
TH> temporally (to prevent an infinite recursion) and the function
TH> which is then bound to KEY will be called."

I think this is a great idea, but it seems like it's pulling the
different ways a bound function can operate internally to the higher
level, complicating what the user has to write.  IOW, you can do the
same inside FUNCTION by testing a series of PREDICATEs.  It does
abstract the more tedious stuff, but maybe that can be a macro inside
the function itself, e.g.

(defun my-bound-function ()
  (or
   (run-in-context outline-minor-mode outline-context-p outline-toggle-children)
   (run-in-context outline-minor-mode eolp self-insert-command)))

This lets the function do more complex things, not just a cond which the
top-level approach is essentially.

I don't know if this can be considered as an alternative.  It's nice
syntactic sugar, for sure.  I've done it the long way several times so I
would welcome anything to make it easier.

Ted





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

* Re: A simple implementation of context-sensitive keys
  2008-09-10  7:17 A simple implementation of context-sensitive keys Tassilo Horn
  2008-09-10 10:36 ` Lennart Borgman (gmail)
  2008-09-10 14:14 ` Sean O'Rourke
@ 2008-09-10 17:49 ` Stefan Monnier
  2008-09-10 19:21   ` Tassilo Horn
  2 siblings, 1 reply; 36+ messages in thread
From: Stefan Monnier @ 2008-09-10 17:49 UTC (permalink / raw)
  To: emacs-devel

> So I've come up with this macro, which creates such a dispatching
> command automagically.  If none of the context predicates match, the
> default command bound to the key will be executed.

Another way to get a similar result is:

(define-key <map> <key> '(menu-item "dummy" <binding>
                          :filter (lambda (binding)
                                    (when <condition> binding))))

It's tempting to use the :enable property instead of :filter, but sadly,
the :enable property is only obeyed by the menu-construction code, not
by the key-lookup code.

In any case, the main problem with such things (whichever way they're
implemented) is that the rest of Emacs doesn't know and/or expect such
condition bindings, so C-h k gives only partial information, and
similarly where-is doesn't know how to tell the whole story.


        Stefan




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

* Re: A simple implementation of context-sensitive keys
  2008-09-10 17:49 ` Stefan Monnier
@ 2008-09-10 19:21   ` Tassilo Horn
  2008-09-11  1:41     ` Stefan Monnier
  0 siblings, 1 reply; 36+ messages in thread
From: Tassilo Horn @ 2008-09-10 19:21 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

Hi Stefan,

> Another way to get a similar result is:
>
> (define-key <map> <key> '(menu-item "dummy" <binding>
>                           :filter (lambda (binding)
>                                     (when <condition> binding))))

Wow, yet another alternative besides the keymap text property Miles
mentioned.

> In any case, the main problem with such things (whichever way they're
> implemented) is that the rest of Emacs doesn't know and/or expect such
> condition bindings, so C-h k gives only partial information, and
> similarly where-is doesn't know how to tell the whole story.

Sure, so I'd say that in general modes shouldn't use such facilities by
default.  Which commands should be executed depending on which context
is a quite subjective decision anyway.  But to have the possibilities
right at hand is great, whichever one you use.

Bye,
Tassilo
-- 
[Emacs] is written in Lisp, which is the only computer language that is
beautiful.  -- Neal Stephenson, _In the Beginning was the Command Line_




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

* Re: A simple implementation of context-sensitive keys
  2008-09-10 19:21   ` Tassilo Horn
@ 2008-09-11  1:41     ` Stefan Monnier
  2008-09-11  7:17       ` Tassilo Horn
  2008-09-11 13:41       ` Lennart Borgman (gmail)
  0 siblings, 2 replies; 36+ messages in thread
From: Stefan Monnier @ 2008-09-11  1:41 UTC (permalink / raw)
  To: emacs-devel

>> In any case, the main problem with such things (whichever way they're
>> implemented) is that the rest of Emacs doesn't know and/or expect such
>> condition bindings, so C-h k gives only partial information, and
>> similarly where-is doesn't know how to tell the whole story.

> Sure, so I'd say that in general modes shouldn't use such facilities by
> default.  Which commands should be executed depending on which context
> is a quite subjective decision anyway.  But to have the possibilities
> right at hand is great, whichever one you use.

I hope we can do better than that, i.e. come up with a way to do
something like what you proposed, but still have where-is, C-h k,
etc... take it into account.


        Stefan




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11  1:41     ` Stefan Monnier
@ 2008-09-11  7:17       ` Tassilo Horn
  2008-09-11 14:40         ` Ted Zlatanov
  2008-09-11 13:41       ` Lennart Borgman (gmail)
  1 sibling, 1 reply; 36+ messages in thread
From: Tassilo Horn @ 2008-09-11  7:17 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

Stefan Monnier <monnier@iro.umontreal.ca> writes:

Hi!

> I hope we can do better than that, i.e. come up with a way to do
> something like what you proposed, but still have where-is, C-h k,
> etc... take it into account.

But what would C-h k say in that case?

TAB is bound to FOO if BAR matches, or to FOO2 if BAR2 matches, else to
FOO3.

Currently with my approach it says:

,----
| TAB (translated from <tab>) runs the command (lambda nil "Execute
| command if eolp matches." (interactive) (if (cond ((user-variable-p
| (quote eolp)) eolp) ((functionp (quote eolp)) (funcall (quote eolp)))
| (t (eval eolp)))...
`----

In my new version (below) I allow arbitrary forms as predicate, so the
command really can get long and unreadably.  I think it would get much
better, if describe-function would pretty-print lambda forms.

--8<---------------cut here---------------start------------->8---
(defmacro define-context-key (keymap key predicate command &optional mode)
  "Bind KEY in KEYMAP to a command which calls COMMAND if PREDICATE is non-nil.

If PREDICATE doesn't match and KEY is normally bound in KEYMAP,
the corresponding default command will be executed.

If KEY isn't normally bound in KEYMAP, MODE (defaulting to
s/KEYMAP/-map//) will be disabled temporally (to prevent an
infinite recursion) and the function which is then bound to KEY
will be called.

Here're two examples:

  ;; TAB on an outline heading toggles visibility
  (define-context-key outline-minor-mode-map
    (kbd \"TAB\")
    ;; This evals to non-nil, if `point' is on a outline-heading
    (save-excursion
      (goto-char (line-beginning-position))
      (looking-at outline-regexp))
    outline-toggle-children)

  ;; TAB at end of line insert a TAB character
  (define-context-key outline-minor-mode-map
    (kbd \"TAB\")
    eolp
    self-insert-command)

The context key for KEYMAP and KEY which was given as last has
precedence, so in this example TAB at the end of a line of an
outline heading inserts a TAB and doesn't toggle the visibility."
  (let* ((mode (or mode
                   (intern (replace-regexp-in-string "-map" ""
                                                     (symbol-name keymap)))))
         (default-fun (lookup-key (symbol-value keymap) (eval key))))
    `(define-key ,keymap ,key
       (lambda ()
         ,(concat "Execute " (symbol-name command)
                  " if " (format "%s" predicate) " matches.")
         (interactive)
         (if (cond
              ((user-variable-p (quote ,predicate))
               ,predicate)
              ((functionp (quote ,predicate))
               (funcall (quote ,predicate)))
              (t
               (eval ,predicate)))
             (call-interactively (quote ,command))
           (if (quote ,default-fun)
               (call-interactively (quote ,default-fun))
             (let (,mode)
               (call-interactively (key-binding ,key)))))))))
--8<---------------cut here---------------end--------------->8---

-- 
Chuck Norris played Russian Roulette with a fully loaded gun and won. 




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

* Re: A simple implementation of context-sensitive keys
  2008-09-10 14:48   ` Miles Bader
  2008-09-10 14:53     ` Juanma Barranquero
@ 2008-09-11  7:35     ` Tassilo Horn
  2008-09-11  8:17       ` Miles Bader
  1 sibling, 1 reply; 36+ messages in thread
From: Tassilo Horn @ 2008-09-11  7:35 UTC (permalink / raw)
  To: Miles Bader; +Cc: Sean O'Rourke, emacs-devel

Miles Bader <miles@gnu.org> writes:

Hi Miles,

> Emacs does have keymap properties...

Hey, nice feature.  I didn't know it till now.  But how to I [re]set
this property in a good fashion?  Currently I think hooking into
after-change-function would be TRTD.

But maybe there's a better way, like telling the font-locking facility
to put keymap foo-map onto all chars which get face foo-face.  In most
cases where I want to have context sensitivity point is on a special
face anyway.

Ah, I think I have found it:

,----[ (info "(elisp)Search-based Fontification") ]
|      However, FACESPEC can also evaluate to a list of this form:
| 
|           (face FACE PROP1 VAL1 PROP2 VAL2...)
`----

So at least it seems possible.  But the font-locking mechanisms are a
bit hairy.  Probably we could add a simple function for hooking into it;
something like

          (define-context-keymap <mode> <matcher> <map>)

Bye,
Tassilo




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11  7:35     ` Tassilo Horn
@ 2008-09-11  8:17       ` Miles Bader
  2008-09-11  8:48         ` Tassilo Horn
  0 siblings, 1 reply; 36+ messages in thread
From: Miles Bader @ 2008-09-11  8:17 UTC (permalink / raw)
  To: Sean O'Rourke; +Cc: emacs-devel

Tassilo Horn <tassilo@member.fsf.org> writes:
> Hey, nice feature.  I didn't know it till now.  But how to I [re]set
> this property in a good fashion?  Currently I think hooking into
> after-change-function would be TRTD.

after-change-functions is a very blunt hammer, and overuse of it is not
good.

I suspect the right thing depends what you're actually trying to do at
the application level.  In that sense, I'm not sure your attempt to
define a single do-everything function like `define-context-keymap' is
actually a very good idea; in many cases it would seem simpler and more
efficient to simply add keymap properties in an application-dependent
manner.

-Miles

-- 
Twice, adv. Once too often.




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11  8:17       ` Miles Bader
@ 2008-09-11  8:48         ` Tassilo Horn
  0 siblings, 0 replies; 36+ messages in thread
From: Tassilo Horn @ 2008-09-11  8:48 UTC (permalink / raw)
  To: Miles Bader; +Cc: Sean O'Rourke, emacs-devel

Miles Bader <miles.bader@necel.com> writes:

Hi Miles,

>> Hey, nice feature.  I didn't know it till now.  But how to I [re]set
>> this property in a good fashion?  Currently I think hooking into
>> after-change-function would be TRTD.
>
> after-change-functions is a very blunt hammer, and overuse of it is
> not good.

I've thought that.

> I suspect the right thing depends what you're actually trying to do at
> the application level.  In that sense, I'm not sure your attempt to
> define a single do-everything function like `define-context-keymap' is
> actually a very good idea;

I agree, so...

> in many cases it would seem simpler and more efficient to simply add
> keymap properties in an application-dependent manner.

... I asked you for a good way to use the font-locking mechanics to add
those properties.  Currently I don't see how I can add only a keymap
property with `font-lock-add-keywords'.

Bye,
Tassilo




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11  1:41     ` Stefan Monnier
  2008-09-11  7:17       ` Tassilo Horn
@ 2008-09-11 13:41       ` Lennart Borgman (gmail)
  2008-09-11 13:48         ` Lennart Borgman (gmail)
  2008-09-11 20:44         ` Stefan Monnier
  1 sibling, 2 replies; 36+ messages in thread
From: Lennart Borgman (gmail) @ 2008-09-11 13:41 UTC (permalink / raw)
  To: Stefan Monnier, Tassilo Horn; +Cc: emacs-devel

Stefan Monnier wrote:
>>> In any case, the main problem with such things (whichever way they're
>>> implemented) is that the rest of Emacs doesn't know and/or expect such
>>> condition bindings, so C-h k gives only partial information, and
>>> similarly where-is doesn't know how to tell the whole story.
> 
>> Sure, so I'd say that in general modes shouldn't use such facilities by
>> default.  Which commands should be executed depending on which context
>> is a quite subjective decision anyway.  But to have the possibilities
>> right at hand is great, whichever one you use.
> 
> I hope we can do better than that, i.e. come up with a way to do
> something like what you proposed, but still have where-is, C-h k,
> etc... take it into account.


I am starting to wonder whether this is the right way to go.

As I said something reminding of this is done in smart-tab, tabkey2 and
hippie-expand. But all these are kind of brute force method to handle
the frustrating situations with the many uncoordinated completion
alternatives there are. And actually I find that special use useful.

However before doing what Tassilo suggest I think it would be better to
look at the background for it.

If I understand it correctly the problem is at least partly how the
keymaps for minor modes cooperates. If they do have the same key binding
then we have the question which one should be used.

And that may very well happen since their is no mechanism at all to
prevent it.

Currently the problem of which minor mode gets the key press is resolved
just by the corresponding minor mode's position in minor-mode-map-alist.
The first one gets it.

There is no notion in where-is, C-h k, etc that there is any key binding
conflict. There is no easy way for users to reorder minor-mode-map-alist.

I think this is where we should start. And after that come back to
Tassilo's suggestion.




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11 13:41       ` Lennart Borgman (gmail)
@ 2008-09-11 13:48         ` Lennart Borgman (gmail)
  2008-09-11 14:22           ` Tassilo Horn
  2008-09-11 20:44         ` Stefan Monnier
  1 sibling, 1 reply; 36+ messages in thread
From: Lennart Borgman (gmail) @ 2008-09-11 13:48 UTC (permalink / raw)
  To: Stefan Monnier, Tassilo Horn; +Cc: emacs-devel

Lennart Borgman (gmail) wrote:
> Currently the problem of which minor mode gets the key press is resolved
> just by the corresponding minor mode's position in minor-mode-map-alist.
> The first one gets it.


Eh, and maybe I should have added that it is easier to understand what I
am talking about after looking here:

  (info "(elisp) Searching Keymaps")




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11 13:48         ` Lennart Borgman (gmail)
@ 2008-09-11 14:22           ` Tassilo Horn
  2008-09-11 20:38             ` Lennart Borgman (gmail)
  0 siblings, 1 reply; 36+ messages in thread
From: Tassilo Horn @ 2008-09-11 14:22 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: Stefan Monnier, emacs-devel

"Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:

Hi!

>> Currently the problem of which minor mode gets the key press is
>> resolved just by the corresponding minor mode's position in
>> minor-mode-map-alist.  The first one gets it.
>
> Eh, and maybe I should have added that it is easier to understand what
>I am talking about after looking here:
>
>   (info "(elisp) Searching Keymaps")

So I guess a first step into the right direction would be to enhance
`describe-key' that it doesn't stop if KEY is found, but to list the
shadowed commands, too.  Something like

,----
| TAB (translated from <tab>) runs the command message-tab, which is an
| interactive compiled Lisp function in
| `/usr/share/emacs/23.0.60/lisp/gnus/message.el'.
| 
| It is bound to TAB in `message-mode-map'.  <== This is new
| 
| (message-tab)
| 
| Complete names according to `message-completion-alist'.
| Execute function specified by `message-tab-body-function' when not in
| those headers.
| 
| It shadows the following commands:         <== This is new
| 
|   `foo'    (bound to TAB in `foo-mode-map')
|   `bar'    (bound to TAB in `bar-mode-map')
|   ...
`----

Bye,
Tassilo
-- 
A child of five could understand this! Fetch me a child of five!




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11  7:17       ` Tassilo Horn
@ 2008-09-11 14:40         ` Ted Zlatanov
  2008-09-11 15:53           ` Tassilo Horn
  0 siblings, 1 reply; 36+ messages in thread
From: Ted Zlatanov @ 2008-09-11 14:40 UTC (permalink / raw)
  To: emacs-devel

On Thu, 11 Sep 2008 09:17:48 +0200 Tassilo Horn <tassilo@member.fsf.org> wrote: 

TH> In my new version (below) I allow arbitrary forms as predicate, so the
TH> command really can get long and unreadably.  I think it would get much
TH> better, if describe-function would pretty-print lambda forms.

I really think this would be endlessly confusing to new users.  "What
does this key do?"  "Take a look at this pretty-printed lambda and
figure it out for yourself."

Ted





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

* Re: A simple implementation of context-sensitive keys
  2008-09-11 14:40         ` Ted Zlatanov
@ 2008-09-11 15:53           ` Tassilo Horn
  0 siblings, 0 replies; 36+ messages in thread
From: Tassilo Horn @ 2008-09-11 15:53 UTC (permalink / raw)
  To: Ted Zlatanov; +Cc: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

Hi Ted,

> TH> In my new version (below) I allow arbitrary forms as predicate, so
> TH> the command really can get long and unreadably.  I think it would
> TH> get much better, if describe-function would pretty-print lambda
> TH> forms.
>
> I really think this would be endlessly confusing to new users.  "What
> does this key do?"  "Take a look at this pretty-printed lambda and
> figure it out for yourself."

Better a pretty-printed lambda than a lambda wrapped at column 80. ;-)

What else could describe-key tell if the bound function is a lambda?
But I agree with you that stock emacs shouldn't do black magic and bin
each key to one function with a clear description.

Bye,
Tassilo




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11 14:22           ` Tassilo Horn
@ 2008-09-11 20:38             ` Lennart Borgman (gmail)
  2008-09-12  6:58               ` Tassilo Horn
  0 siblings, 1 reply; 36+ messages in thread
From: Lennart Borgman (gmail) @ 2008-09-11 20:38 UTC (permalink / raw)
  To: Lennart Borgman (gmail), Stefan Monnier, emacs-devel

Tassilo Horn wrote:
> "Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:
> 
> Hi!
> 
>>> Currently the problem of which minor mode gets the key press is
>>> resolved just by the corresponding minor mode's position in
>>> minor-mode-map-alist.  The first one gets it.
>> Eh, and maybe I should have added that it is easier to understand what
>> I am talking about after looking here:
>>
>>   (info "(elisp) Searching Keymaps")
> 
> So I guess a first step into the right direction would be to enhance
> `describe-key' that it doesn't stop if KEY is found, but to list the
> shadowed commands, too.  Something like

If you say that this is the first step so, yes ... ;-)

> ,----
> | TAB (translated from <tab>) runs the command message-tab, which is an
> | interactive compiled Lisp function in
> | `/usr/share/emacs/23.0.60/lisp/gnus/message.el'.
> | 
> | It is bound to TAB in `message-mode-map'.  <== This is new

There is currently no function in Emacs to find the keymap variable
name. However I wrote the command `describe-key-and-map-briefly' that
tries to find the keymap variable name. This is a bit tricky and I am
sure that you can construct cases where it does not work. However so far
I have not found any example where it does not work.

Here is the output from it

  <f1> c is bound to `describe-key-and-map-briefly' in `global-map'

and here is the output from `describe-key-briefly' (the default binding
for <f1> c):

  <f1> c runs the command describe-key-and-map-briefly

The function is in this file

http://bazaar.launchpad.net/~nxhtml/nxhtml/main/annotate/52?file_id=ourcommentsutil.el-20080724174035-zgon4j679232cch3-182


> | (message-tab)
> | 
> | Complete names according to `message-completion-alist'.
> | Execute function specified by `message-tab-body-function' when not in
> | those headers.
> | 
> | It shadows the following commands:         <== This is new
> | 
> |   `foo'    (bound to TAB in `foo-mode-map')
> |   `bar'    (bound to TAB in `bar-mode-map')
> |   ...
> `----

Yes, something like that.

> Bye,
> Tassilo




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11 13:41       ` Lennart Borgman (gmail)
  2008-09-11 13:48         ` Lennart Borgman (gmail)
@ 2008-09-11 20:44         ` Stefan Monnier
  2008-09-11 21:14           ` Lennart Borgman (gmail)
  1 sibling, 1 reply; 36+ messages in thread
From: Stefan Monnier @ 2008-09-11 20:44 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: Tassilo Horn, emacs-devel

>> I hope we can do better than that, i.e. come up with a way to do
>> something like what you proposed, but still have where-is, C-h k,
>> etc... take it into account.
> I am starting to wonder whether this is the right way to go.

I'm not sure it is either.

> There is no notion in where-is, C-h k, etc that there is any key binding
> conflict. There is no easy way for users to reorder minor-mode-map-alist.

The problem is a lot more general than conflicts between minor modes.
There are things also like mouse-2 bindings that only work locally
(either implemented via `keymap' text-properties or by a normal binding
that checks a predicate and delegates to some other command if that
fails) where the various possible "conflicting" bindings can be spread
between minor modes, major modes and global bindings.


        Stefan




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11 20:44         ` Stefan Monnier
@ 2008-09-11 21:14           ` Lennart Borgman (gmail)
  2008-09-12  1:33             ` Stefan Monnier
  0 siblings, 1 reply; 36+ messages in thread
From: Lennart Borgman (gmail) @ 2008-09-11 21:14 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tassilo Horn, emacs-devel

Stefan Monnier wrote:
>>> I hope we can do better than that, i.e. come up with a way to do
>>> something like what you proposed, but still have where-is, C-h k,
>>> etc... take it into account.
>> I am starting to wonder whether this is the right way to go.
> 
> I'm not sure it is either.
> 
>> There is no notion in where-is, C-h k, etc that there is any key binding
>> conflict. There is no easy way for users to reorder minor-mode-map-alist.
> 
> The problem is a lot more general than conflicts between minor modes.
> There are things also like mouse-2 bindings that only work locally
> (either implemented via `keymap' text-properties or by a normal binding
> that checks a predicate and delegates to some other command if that
> fails) where the various possible "conflicting" bindings can be spread
> between minor modes, major modes and global bindings.

Some of this potential conflicts are resolved by the key binding
conventions:

  (info "(elisp) Key Binding Conventions")

But there is nothing there that help for conflicts between minor modes.

The only thing I can think of that can help is giving some way to tell
which minor mode should come first, ie some priority handling.




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11 21:14           ` Lennart Borgman (gmail)
@ 2008-09-12  1:33             ` Stefan Monnier
  2008-09-12  8:29               ` Lennart Borgman (gmail)
  0 siblings, 1 reply; 36+ messages in thread
From: Stefan Monnier @ 2008-09-12  1:33 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: Tassilo Horn, emacs-devel

> Some of this potential conflicts are resolved by the key binding
> conventions:
>   (info "(elisp) Key Binding Conventions")

No, because these are not accidental conflicts.  The use of the same key
is voluntary.


        Stefan




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

* Re: A simple implementation of context-sensitive keys
  2008-09-11 20:38             ` Lennart Borgman (gmail)
@ 2008-09-12  6:58               ` Tassilo Horn
  2008-09-12  8:34                 ` Lennart Borgman (gmail)
  0 siblings, 1 reply; 36+ messages in thread
From: Tassilo Horn @ 2008-09-12  6:58 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: Stefan Monnier, emacs-devel

"Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:

Hi Lennart,

>> So I guess a first step into the right direction would be to enhance
>> `describe-key' that it doesn't stop if KEY is found, but to list the
>> shadowed commands, too.  Something like
>
> If you say that this is the first step so, yes ... ;-)
>
>> ,----
>> | TAB (translated from <tab>) runs the command message-tab, which is an
>> | interactive compiled Lisp function in
>> | `/usr/share/emacs/23.0.60/lisp/gnus/message.el'.
>> | 
>> | It is bound to TAB in `message-mode-map'.  <== This is new
>
> There is currently no function in Emacs to find the keymap variable
> name.

I think you could reimplement the key lookup procedure you referenced
and don't stop searching when KEY is found.  Then you know the name of
the map.

> However I wrote the command `describe-key-and-map-briefly' that tries
> to find the keymap variable name. This is a bit tricky and I am sure
> that you can construct cases where it does not work. However so far I
> have not found any example where it does not work.

Hey cool.  Here's a function to find all commands bound to key.  The car
is the command which is executed, the cdr is the list of shadowed
commands.

--8<---------------cut here---------------start------------->8---
(defun lookup-key-bindings (key)
  (let (list)
    (dolist (map (current-active-maps))
      (let ((cmd (lookup-key map key)))
        (when (and cmd
                   (not (numberp cmd)))
          (add-to-list 'list cmd t))))
    list))

(lookup-key-bindings (kbd "C-f"))
;; ==C-j==> (paredit-forward forward-char)
--8<---------------cut here---------------end--------------->8---

So we have to combine those functions and are done. ;-)

Bye,
Tassilo




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

* Re: A simple implementation of context-sensitive keys
  2008-09-12  1:33             ` Stefan Monnier
@ 2008-09-12  8:29               ` Lennart Borgman (gmail)
  0 siblings, 0 replies; 36+ messages in thread
From: Lennart Borgman (gmail) @ 2008-09-12  8:29 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tassilo Horn, emacs-devel

Stefan Monnier wrote:
>> Some of this potential conflicts are resolved by the key binding
>> conventions:
>>   (info "(elisp) Key Binding Conventions")
> 
> No, because these are not accidental conflicts.  The use of the same key
> is voluntary.


Yes, of course. I did not mean those.




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

* Re: A simple implementation of context-sensitive keys
  2008-09-12  6:58               ` Tassilo Horn
@ 2008-09-12  8:34                 ` Lennart Borgman (gmail)
  2008-09-12  9:47                   ` Tassilo Horn
  0 siblings, 1 reply; 36+ messages in thread
From: Lennart Borgman (gmail) @ 2008-09-12  8:34 UTC (permalink / raw)
  To: Lennart Borgman (gmail), Stefan Monnier, emacs-devel

Tassilo Horn wrote:
>> There is currently no function in Emacs to find the keymap variable
>> name.
> 
> I think you could reimplement the key lookup procedure you referenced
> and don't stop searching when KEY is found.  Then you know the name of
> the map.

What do you mean? Please write the code and show it.





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

* Re: A simple implementation of context-sensitive keys
  2008-09-12  8:34                 ` Lennart Borgman (gmail)
@ 2008-09-12  9:47                   ` Tassilo Horn
  2008-09-12 11:00                     ` Lennart Borgman
  0 siblings, 1 reply; 36+ messages in thread
From: Tassilo Horn @ 2008-09-12  9:47 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: Stefan Monnier, emacs-devel

"Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:

Hi Lennart,

>> I think you could reimplement the key lookup procedure you referenced
>> and don't stop searching when KEY is found.  Then you know the name
>> of the map.
>
> What do you mean? Please write the code and show it.

Sorry, no time to write the code now.  What I mean is that in

  (info "(elisp)Searching Keymaps")

there's the pseudocode how emacs finds the command for a key.  Now you
can surrogate "FIND-IN" with lookup-key and see if the key is bound in
the map.  In that code you know the map or at least the mode, cause you
either have the variable directly (like overriding-local-map) or you
walk an alist of the form ((mode-name . keymap)...) in the case of
FIND-IN-ANY.

Bye,
Tassilo




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

* Re: A simple implementation of context-sensitive keys
  2008-09-12  9:47                   ` Tassilo Horn
@ 2008-09-12 11:00                     ` Lennart Borgman
  2008-09-12 16:13                       ` Tassilo Horn
  0 siblings, 1 reply; 36+ messages in thread
From: Lennart Borgman @ 2008-09-12 11:00 UTC (permalink / raw)
  To: Lennart Borgman (gmail), Stefan Monnier, emacs-devel

On 9/12/08, Tassilo Horn <tassilo@member.fsf.org> wrote:
> "Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:
>
> Hi Lennart,
>
> >> I think you could reimplement the key lookup procedure you referenced
> >> and don't stop searching when KEY is found.  Then you know the name
> >> of the map.
> >
> > What do you mean? Please write the code and show it.
>
> Sorry, no time to write the code now.  What I mean is that in
>
>  (info "(elisp)Searching Keymaps")
>
> there's the pseudocode how emacs finds the command for a key.  Now you
> can surrogate "FIND-IN" with lookup-key and see if the key is bound in
> the map.  In that code you know the map or at least the mode, cause you
> either have the variable directly (like overriding-local-map) or you
> walk an alist of the form ((mode-name . keymap)...) in the case of
> FIND-IN-ANY.

It would be good if that where true, but it is not. You have to take a
closer look to understand how this works. I think a good start might
be the code I sent before.

> Bye,
> Tassilo
>




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

* Re: A simple implementation of context-sensitive keys
  2008-09-12 11:00                     ` Lennart Borgman
@ 2008-09-12 16:13                       ` Tassilo Horn
  2008-09-12 23:46                         ` Lennart Borgman (gmail)
  0 siblings, 1 reply; 36+ messages in thread
From: Tassilo Horn @ 2008-09-12 16:13 UTC (permalink / raw)
  To: Lennart Borgman; +Cc: Stefan Monnier, emacs-devel

"Lennart Borgman" <lennart.borgman@gmail.com> writes:

Hi Lennart,

>> Sorry, no time to write the code now.  What I mean is that in
>>
>>  (info "(elisp)Searching Keymaps")
>>
>> there's the pseudocode how emacs finds the command for a key.  Now
>> you can surrogate "FIND-IN" with lookup-key and see if the key is
>> bound in the map.  In that code you know the map or at least the
>> mode, cause you either have the variable directly (like
>> overriding-local-map) or you walk an alist of the form ((mode-name
>> . keymap)...) in the case of FIND-IN-ANY.
>
> It would be good if that where true, but it is not. You have to take a
> closer look to understand how this works. I think a good start might
> be the code I sent before.

Here's a q&d implementation of what I thought should do the trick.  It
works for me, although only very briefly tested.

--8<---------------cut here---------------start------------->8---
(defun find-key-commands (key)
  (let (list)
    (when overriding-terminal-local-map
      (let ((c (lookup-key overriding-terminal-local-map key))) 
        (when (and c
                   (not (numberp c)))
          (add-to-list 'list (cons 'overriding-terminal-local-map c) t))))
    (when overriding-local-map
      (let ((c (lookup-key overriding-local-map key))) 
        (when (and c
                   (not (numberp c)))
          (add-to-list 'list (cons 'overriding-local-map c) t))))
    (let ((prop-map (get-char-property (point) 'keymap)))
      (when prop-map
        (let ((c (lookup-key prop-map key))) 
          (when (and c
                     (not (numberp c)))
            (add-to-list 'list (cons 'char-property-keymap c) t)))))
    (dolist (alist '(emulation-mode-map-alists
                     minor-mode-overriding-map-alist
                     minor-mode-map-alist))
      (dolist (x (symbol-value alist))
        (let ((mapname (car x))
              (map (cdr x)))
          (when map
            (let ((c (lookup-key map key))) 
              (when (and c
                         (not (numberp c)))
                (add-to-list 'list (cons mapname c) t)))))))
    (when (get-text-property (point) 'local-map)
      (let ((prop-map (get-char-property (point) 'local-map)))
        (when prop-map
          (let ((c (lookup-key prop-map key))) 
            (when (and c
                       (not (numberp c)))
              (add-to-list 'list (cons 'char-property-local-map c) t))))))
    (when (current-local-map)
      (let ((c (lookup-key (current-local-map) key))) 
        (when (and c
                   (not (numberp c)))
          (add-to-list 'list (cons 'current-local-map c) t))))
    (let ((c (lookup-key (current-global-map) key))) 
      (when (and c
                 (not (numberp c)))
        (add-to-list 'list (cons 'current-global-map c) t)))
    list))

(find-key-commands (kbd "M-1"))
;; ==> ((window-number-mode lambda nil (interactive) (window-number-select 1)) (current-global-map . digit-argument))
(find-key-commands (kbd "C-f"))
;; ==> ((paredit-mode . paredit-forward) (current-global-map . forward-char))
--8<---------------cut here---------------end--------------->8---

Bye,
Tassilo




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

* Re: A simple implementation of context-sensitive keys
  2008-09-12 16:13                       ` Tassilo Horn
@ 2008-09-12 23:46                         ` Lennart Borgman (gmail)
  2008-09-13  7:28                           ` Tassilo Horn
  0 siblings, 1 reply; 36+ messages in thread
From: Lennart Borgman (gmail) @ 2008-09-12 23:46 UTC (permalink / raw)
  To: Tassilo Horn, emacs-devel

Tassilo Horn wrote:
> "Lennart Borgman" <lennart.borgman@gmail.com> writes:
> 
> Hi Lennart,
> 
>>> Sorry, no time to write the code now.  What I mean is that in
>>>
>>>  (info "(elisp)Searching Keymaps")
>>>
>>> there's the pseudocode how emacs finds the command for a key.  Now
>>> you can surrogate "FIND-IN" with lookup-key and see if the key is
>>> bound in the map.  In that code you know the map or at least the
>>> mode, cause you either have the variable directly (like
>>> overriding-local-map) or you walk an alist of the form ((mode-name
>>> . keymap)...) in the case of FIND-IN-ANY.
>> It would be good if that where true, but it is not. You have to take a
>> closer look to understand how this works. I think a good start might
>> be the code I sent before.
> 
> Here's a q&d implementation of what I thought should do the trick.  It
> works for me, although only very briefly tested.
> 
> --8<---------------cut here---------------start------------->8---
> (defun find-key-commands (key)
>   (let (list)
>     (when overriding-terminal-local-map


Yes, the structure of the key binding search must be mirrored in the
routine. But the problem I tried to solve was rather to find the keymap
variable names.

You do not have those names available anywhere really. You have to guess.

But combining the mirrored structure with the routine that guesses the
keymap variable name would be the best I think.




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

* Re: A simple implementation of context-sensitive keys
  2008-09-12 23:46                         ` Lennart Borgman (gmail)
@ 2008-09-13  7:28                           ` Tassilo Horn
  2008-09-13  9:32                             ` Lennart Borgman (gmail)
  0 siblings, 1 reply; 36+ messages in thread
From: Tassilo Horn @ 2008-09-13  7:28 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: emacs-devel

"Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:

Hi Lennart,

>> Here's a q&d implementation of what I thought should do the trick.
>> It works for me, although only very briefly tested.
>> 
>> --8<---------------cut here---------------start------------->8---
>> (defun find-key-commands (key)
>>   (let (list)
>>     (when overriding-terminal-local-map
>
>
> Yes, the structure of the key binding search must be mirrored in the
> routine. But the problem I tried to solve was rather to find the
> keymap variable names.

Ok, that's true.  You either have the keymap variable name or the mode
name.  In most cases appending "-map" to the mode name makes the keymap
name.  And even it that fails for some modes, I thing something like

  TAB ist bound to `do-foo' in `foo-mode'.

is not too bad.

> You do not have those names available anywhere really. You have to
> guess.

Maybe an adapted version of `apropos-value' might do the trick.  As it's
now it's much too slow and fails with large keymaps cause it uses their
printed representation as regexp (which gets too long then).  The
`apropos-value' we need can skip everything which is not a list whose
car is 'keymap.  And we don't need to use strings and regexp matching,
but simply `eq'.

> But combining the mirrored structure with the routine that guesses the
> keymap variable name would be the best I think.

Yeah, something like that.

Bye,
Tassilo
-- 
* delYsid has mortgage, opportunity and penis in his score file.
<delYsid> thats pretty effective against spam
<Luke> aren't you worried about missing opportunities to mortgage
       your penis?




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

* Re: A simple implementation of context-sensitive keys
  2008-09-13  7:28                           ` Tassilo Horn
@ 2008-09-13  9:32                             ` Lennart Borgman (gmail)
  2008-09-15  7:26                               ` Tassilo Horn
  0 siblings, 1 reply; 36+ messages in thread
From: Lennart Borgman (gmail) @ 2008-09-13  9:32 UTC (permalink / raw)
  To: Tassilo Horn, emacs-devel

Tassilo Horn wrote:
> "Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:
> 
> Hi Lennart,
> 
>>> Here's a q&d implementation of what I thought should do the trick.
>>> It works for me, although only very briefly tested.
>>>
>>> --8<---------------cut here---------------start------------->8---
>>> (defun find-key-commands (key)
>>>   (let (list)
>>>     (when overriding-terminal-local-map
>>
>> Yes, the structure of the key binding search must be mirrored in the
>> routine. But the problem I tried to solve was rather to find the
>> keymap variable names.
> 
> Ok, that's true.  You either have the keymap variable name or the mode
> name.  In most cases appending "-map" to the mode name makes the keymap
> name.  And even it that fails for some modes, I thing something like
> 
>   TAB ist bound to `do-foo' in `foo-mode'.
> 
> is not too bad.

Yes, it might be good to combine the output with this information when
it looks reliable.

>> You do not have those names available anywhere really. You have to
>> guess.
> 
> Maybe an adapted version of `apropos-value' might do the trick.  As it's
> now it's much too slow

Did you try describe-key-and-map-briefly?

>> But combining the mirrored structure with the routine that guesses the
>> keymap variable name would be the best I think.
> 
> Yeah, something like that.
> 
> Bye,
> Tassilo




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

* Re: A simple implementation of context-sensitive keys
  2008-09-13  9:32                             ` Lennart Borgman (gmail)
@ 2008-09-15  7:26                               ` Tassilo Horn
  2008-09-15 22:39                                 ` Lennart Borgman (gmail)
  0 siblings, 1 reply; 36+ messages in thread
From: Tassilo Horn @ 2008-09-15  7:26 UTC (permalink / raw)
  To: Lennart Borgman (gmail); +Cc: emacs-devel

"Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:

Hi Lennart,

>> Maybe an adapted version of `apropos-value' might do the trick.  As
>> it's now it's much too slow
>
> Did you try describe-key-and-map-briefly?

Not till now.  I'm loaded with other work. :-(

Bye,
Tassilo




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

* Re: A simple implementation of context-sensitive keys
  2008-09-15  7:26                               ` Tassilo Horn
@ 2008-09-15 22:39                                 ` Lennart Borgman (gmail)
  0 siblings, 0 replies; 36+ messages in thread
From: Lennart Borgman (gmail) @ 2008-09-15 22:39 UTC (permalink / raw)
  To: Lennart Borgman (gmail), emacs-devel

Tassilo Horn wrote:
> "Lennart Borgman (gmail)" <lennart.borgman@gmail.com> writes:
> 
> Hi Lennart,
> 
>>> Maybe an adapted version of `apropos-value' might do the trick.  As
>>> it's now it's much too slow
>> Did you try describe-key-and-map-briefly?
> 
> Not till now.  I'm loaded with other work. :-(

Ok, I have added the function key-bindings to ourcomments-util.el. This
function fetches more detailed information about a key binding,
shadowing etc.

I think this can be used in describe-key.

What is missing now is a corresponding enhancement of where-is.




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

end of thread, other threads:[~2008-09-15 22:39 UTC | newest]

Thread overview: 36+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-10  7:17 A simple implementation of context-sensitive keys Tassilo Horn
2008-09-10 10:36 ` Lennart Borgman (gmail)
2008-09-10 10:57   ` Tassilo Horn
2008-09-10 16:43     ` Ted Zlatanov
2008-09-10 14:14 ` Sean O'Rourke
2008-09-10 14:48   ` Miles Bader
2008-09-10 14:53     ` Juanma Barranquero
2008-09-10 15:17       ` Sean O'Rourke
2008-09-10 15:32         ` Juanma Barranquero
2008-09-11  7:35     ` Tassilo Horn
2008-09-11  8:17       ` Miles Bader
2008-09-11  8:48         ` Tassilo Horn
2008-09-10 17:49 ` Stefan Monnier
2008-09-10 19:21   ` Tassilo Horn
2008-09-11  1:41     ` Stefan Monnier
2008-09-11  7:17       ` Tassilo Horn
2008-09-11 14:40         ` Ted Zlatanov
2008-09-11 15:53           ` Tassilo Horn
2008-09-11 13:41       ` Lennart Borgman (gmail)
2008-09-11 13:48         ` Lennart Borgman (gmail)
2008-09-11 14:22           ` Tassilo Horn
2008-09-11 20:38             ` Lennart Borgman (gmail)
2008-09-12  6:58               ` Tassilo Horn
2008-09-12  8:34                 ` Lennart Borgman (gmail)
2008-09-12  9:47                   ` Tassilo Horn
2008-09-12 11:00                     ` Lennart Borgman
2008-09-12 16:13                       ` Tassilo Horn
2008-09-12 23:46                         ` Lennart Borgman (gmail)
2008-09-13  7:28                           ` Tassilo Horn
2008-09-13  9:32                             ` Lennart Borgman (gmail)
2008-09-15  7:26                               ` Tassilo Horn
2008-09-15 22:39                                 ` Lennart Borgman (gmail)
2008-09-11 20:44         ` Stefan Monnier
2008-09-11 21:14           ` Lennart Borgman (gmail)
2008-09-12  1:33             ` Stefan Monnier
2008-09-12  8:29               ` Lennart Borgman (gmail)

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