Giter Site home page Giter Site logo

Comments (6)

marczz avatar marczz commented on June 13, 2024 1

The elisp manual is not so clear about define-key, it only says

The argument BINDING can be any Lisp object, but only certain types are meaningful. (For a list of meaningful types, see *note Key Lookup::.)

If it was so, as you say, we should find the cons under the "anything else" category, and it does not fit there.

But if you look at the docstring of define-key, in the description of (define-key KEYMAP KEY DEF) a list of possible values for DEF is given among which you find:

a cons (STRING . DEFN), meaning that DEFN is the definition (DEFN should be a valid definition in its own right),

We just use that and so for DEFN we have the choice between a command, a string treated as a keyboard macro, a keymap, a symbol which stands for its function definition.
In my first example and in your examples the CDR of the cons is a keymap.
In my second example I use a symbol, but the value slot cannot be used directly, because the symbol stands for its function definition.
So I fill also the function slot with (fset 'testmap testmap).

from emacs-which-key.

justbur avatar justbur commented on June 13, 2024 1

A keymap is a list with the symbol keymap as its CAR (doc). Therefore, (testmap) is not a keymap. That's one issue. By the way you can use make-sparse-keymap if you like (doc).

You also have to pay attention to what the DEF is evaluating to. In the case of commands, you want the DEF to evaluate to a symbol pointing to a command. In the case of keymaps, you want the DEF to evaluate to the underlying keymap list/object, not to a symbol pointing to the keymap (doc).

Some examples might help

This works, because the DEF evaluates to a keymap object.

(define-key parent-map "k" '(keymap))

This doesn't work, because the DEF evaluates to a symbol pointing to a keymap object.

(setq testmap '(keymap))
(define-key parent-map "k" 'testmap)

This works again. Note the quotation.

(setq testmap '(keymap))
(define-key parent-map "k" testmap)

This doesn't work, because (testmap) is not a keymap object (it is not a list beginning with the keymap symbol).

(define-key parent-map "k" '(testmap))

Now, adding the CONS form to name the definition follows the same rules. You just have to make sure that the CDR evaluates to a keymap as before. This will work

(define-key parent-map "k" '("name" . (keymap)))

This will not

(define-key parent-map "k" '("name" . '(keymap)))

This will not work, because DEF evaluates to ("name" . testmap) and testmap is not a keymap object (it is a symbol pointing to one).

(setq testmap '(keymap))
(define-key parent-map "k" '("name" . testmap))

This will work again, because cons evaluates both of its arguments before constructing the new CONS form.

(setq testmap '(keymap))
(define-key parent-map "k" (cons "name" testmap))

from emacs-which-key.

dankessler avatar dankessler commented on June 13, 2024

I got stuck in a very similar place as you, and ultimately found the explanation here. I too wonder if the documentation could be amended to show an example where a description is provided and a key is bound to a non-trivial keymap.

Suppose for example I have already constructed a keymap, and it is referred to by the symbol some-prefix-map. Then, if I understand correctly, the examples could read

(define-key some-map "f" '("foo" . command-foo))
(define-key some-map "b" (cons "bar-prefix" some-prefix-map))

and

(define-key some-map "f" 'long-command-name-foo)
(define-key some-map "b" some-prefix-map)
(which-key-add-keymap-based-replacements some-map
  "f" '("foo" . long-command-name-foo)
  "b" (cons "bar-prefix" some-prefix-map))

from emacs-which-key.

dankessler avatar dankessler commented on June 13, 2024

At the same time, I still can't quite wrap my head around how this is working on a deep level. My understanding is that the correct usage is to pass a BINDING that is a cons whose car is a descriptive string and whose cdr is a keymap (literally a keymap, not a symbol referring to a keymap). My understanding is that BINDING should get processed according to this logic, and to my naive eyes it looks the cons cell as passed would fall under the "anything else" category (the cons is a list, but its car is neither the symbol keymap nor lambda).

from emacs-which-key.

marczz avatar marczz commented on June 13, 2024

Thank you Justin, the added example in 1692a1e will help to understand the syntax.
The way of understanding examples is subjective, and your mileage may vary, but I still find confusing the wording of

(define-key some-map "b" '("bar-prefix" . (keymap)))

What is the meaning of keymap here? If it is the literal symbol keymap that constitute the car of any keymap we should rather write:

 (define-key some-map "b" '("bar-prefix" . (keymap ...)))

If it designates any keymap the parentheses are not relevant because the keymap is yet a cons, so the parentheses are included in the keymap.
In this case i would rather write it:

   (define-key some-map "b" '("bar-prefix" . <some keymap>))

The use of angle brackets to designate an arbitrary parameter is a posix convention, with an alternative of words separated by underlines, usually in italic.

But the main thing is by writing <some keymap> or some_keymap or an-other-map like you have used some-map the user understand that it is a generic slot to be filled with the corresponding object.

This may be quite pernickety, and the added example should dispel any confusion

from emacs-which-key.

marczz avatar marczz commented on June 13, 2024

In the examples that I gave in my initial post, I omitted define-prefix-command which is equivalent to the use of fset but more elegant, with it you would write:

 (define-prefix-command 'testmap)
 (define-key global-map [?\C-:] '("test map" . testmap))

Such an example might be added in the README.

from emacs-which-key.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.