bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

classic Classic list List threaded Threaded
32 messages Options
12
Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

積丹尼 Dan Jacobson
(info "(emacs) Keymaps") should mention the best way to view a keymap.

If the user just uses describe-variable, he will see

 (67108910 . flyspell-auto-correct-word)

etc. So mention he should use describe-bindings.



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Drew Adams
> (info "(emacs) Keymaps") should mention the best way to view a keymap.
> If the user just uses describe-variable, he will see
>  (67108910 . flyspell-auto-correct-word)
> etc. So mention he should use `describe-bindings'.

`describe-bindings' does not describe the bindings of a given
keymap.

S?he should use `describe-keymap' (`C-h M-k'), from `help-fns+.el'.

It describes the bindings in a keymap in the usual human-readable
way.  You are prompted for a keymap variable (e.g., `ctl-x-map`),
with completion.  (Non-interactively, the argument can be a keymap
itself or a keymap variable.)

This or similar code should be in vanilla Emacs.  (I've offered
any and all of my code.)

https://www.emacswiki.org/emacs/download/help-fns%2b.el



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Stefan Kangas
In reply to this post by 積丹尼 Dan Jacobson
Drew Adams <[hidden email]> writes:

>> (info "(emacs) Keymaps") should mention the best way to view a keymap.
>> If the user just uses describe-variable, he will see
>>  (67108910 . flyspell-auto-correct-word)
>> etc. So mention he should use `describe-bindings'.
>
> `describe-bindings' does not describe the bindings of a given
> keymap.
>
> S?he should use `describe-keymap' (`C-h M-k'), from `help-fns+.el'.
>
> It describes the bindings in a keymap in the usual human-readable
> way.  You are prompted for a keymap variable (e.g., `ctl-x-map`),
> with completion.  (Non-interactively, the argument can be a keymap
> itself or a keymap variable.)
>
> This or similar code should be in vanilla Emacs.  (I've offered
> any and all of my code.)
>
> https://www.emacswiki.org/emacs/download/help-fns%2b.el

I copied and  evaluated the describe-keymap function, but when I typed
M-x describe-keymap I got the following error:

save-current-buffer: Symbol’s function definition is void:
Info-make-manuals-xref

I couldn't find the definition of a function by that name in the file
you indicated, so I'm guessing there's some dependencies involved and
that I don't have.  Could you provide a version of this function which
works on current master without requiring these extra packages?

Thanks,
Stefan Kangas



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Drew Adams
> > `describe-bindings' does not describe the bindings of a given

> > keymap.
> >
> > S?he should use `describe-keymap' (`C-h M-k'), from `help-fns+.el'.
> >
> > It describes the bindings in a keymap in the usual human-readable
> > way.  You are prompted for a keymap variable (e.g., `ctl-x-map`),
> > with completion.  (Non-interactively, the argument can be a keymap
> > itself or a keymap variable.)
> >
> > This or similar code should be in vanilla Emacs.  (I've offered
> > any and all of my code.)
> >
> > https://urldefense.proofpoint.com/v2/url?u=https-
> 3A__www.emacswiki.org_emacs_download_help-2Dfns-
> 252b.el&d=DwIFaQ&c=RoP1YumCXCgaWHvlZYR8PZh8Bv7qIrMUB65eapI_JnE&r=kI3P6l
> jGv6CTHIKju0jqInF6AOwMCYRDQUmqX22rJ98&m=yA0xm3W_AykCUU9THjbJlpxhVhQlA3X
> AncZSWRe2Wc0&s=P11PKX0Nhl4PaaXOh-0ZYcfDDhlprpw4pnWG5QqizvQ&e=
>
> I copied and  evaluated the describe-keymap function, but when I typed
> M-x describe-keymap I got the following error:
>
> save-current-buffer: Symbol’s function definition is void:
> Info-make-manuals-xref
>
> I couldn't find the definition of a function by that name in the file
> you indicated, so I'm guessing there's some dependencies involved and
> that I don't have.  Could you provide a version of this function which
> works on current master without requiring these extra packages?
`Info-make-manuals-xref' _is_ defined in
help-fns+.el.  And no extra packages are needed
for help-fns+.el.

But adding the functionality of
`Info-make-manuals-xref' is not necessarily
something that vanilla Emacs would want now.
That should probably be discussed separately.

Similarly, there are other features used by
`describe-keymap' that I'm not sure you want to
add now to vanilla Emacs.  And you definitely
don't need the code that supports older Emacs
versions.

Bottom line, if you want to add only bare-bones
`describe-keymap' to vanilla Emacs then just
use the attached definition.


throw-describe-keymap-for-vanilla.el (3K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Stefan Kangas
Drew Adams <[hidden email]> writes:

> `Info-make-manuals-xref' _is_ defined in
> help-fns+.el.

OK, sorry about that.  I must have missed it.

> Bottom line, if you want to add only bare-bones
> `describe-keymap' to vanilla Emacs then just
> use the attached definition.

Thanks.  I tried it, and I personally think it's a useful addition.
Maybe others disagree.  I was going to pack it up as a patch for
review but I have some questions about the code first.

> Non-interactively:
> * KEYMAP can be such a keymap variable or a keymap.
> * Non-nil optional arg SEARCH-SYMBOLS-P means that if KEYMAP is not a
>   symbol then search all variables for one whose value is KEYMAP."

Is the purpose of SEARCH-SYMBOLS-P just to allow for calling it like this:

    (describe-keymap 'my-keymap t)
    (describe-keymap my-keymap t)

And have it work automatically?  Or am I missing something?  Also see below.

>   (unless (and (symbolp keymap)  (boundp keymap)  (keymapp (symbol-value keymap)))
>     (if (not (keymapp keymap))
>         (error "%sot a keymap%s"
>                (if (symbolp keymap) (format "`%S' is n" keymap) "N")
>                (if (symbolp keymap) " variable" ""))
>       (let ((sym  nil))
>         (when search-symbols-p
>           (setq sym  (catch 'describe-keymap
>                        (mapatoms (lambda (symb) (when (and (boundp symb)
>                                                       (eq (symbol-value symb) keymap)
>                                                       (not (eq symb 'keymap))
>                                                       (throw 'describe-keymap symb)))))
>                        nil)))
>         (unless sym
>           (setq sym  (gentemp "KEYMAP OBJECT (no variable) "))
>           (set sym keymap))
>         (setq keymap  sym))))

I admit that I find this code a bit hard to follow.  If I understand
correctly, then most of this can be removed if we don't want to
support SEARCH-SYMBOLS-P, and instead just require that the KEYMAP
argument is a symbol.  Is that correct or am I missing something?

I'm sort of leaning towards simplifying this by removing the
SEARCH-SYMBOLS-P argument, but I might not understand the use case
here.  If I'm missing something, could you please briefly describe the
use case for that and if and why it's important to keep?

>   (setq keymap  (or (ignore-errors (indirect-variable keymap))  keymap)) ; Follow aliasing.
>   (let* ((name  (symbol-name keymap))
>          (doc   (let ((raw-doc  (documentation-property keymap 'variable-documentation 'RAW)))
>                   (substitute-command-keys raw-doc)))

Why not just say (documentation-property keymap 'variable-documentation)
without the 'RAW argument?  That should have the same effect as
passing the 'RAW argument and then calling substitute-command-keys on
the result, AFAICT.

>          (doc   (and (not (equal "" doc))  doc)))

Is this to allow us to simply say (when doc ...) below instead of
(when (not (equal "" doc)) ...) or am I missing something?

Thanks,
Stefan Kangas



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Drew Adams
> > Non-interactively:
> > * KEYMAP can be such a keymap variable or a keymap.
> > * Non-nil optional arg SEARCH-SYMBOLS-P means that if KEYMAP is not a
> >   symbol then search all variables for one whose value is KEYMAP."
>
> Is the purpose of SEARCH-SYMBOLS-P just to allow for calling it like
> this:
>     (describe-keymap 'my-keymap t)
>     (describe-keymap my-keymap t)
>
> And have it work automatically?  Or am I missing something?  Also see
> below.

KEYMAP can be a keymap, instead of a symbol.

(This was not the case originally.  I added handling
this case later, as it was requested and turned out
to be useful.  It's not rare to have a keymap object
ready-to-hand and without its variable.  This lets
you not only see the bindings but also identify the
keymap.)

If it's not a symbol there might still be a symbol
that has it as value.  Non-nil SEARCH-SYMBOLS-P
means try to find such a symbol.

If such a symbol is found then the help is better -
it tells you more about the keymap and its context,
by (1) providing its doc (in addition to listing the
key bindings) and even just (2) providing its name,
letting you know (typically) what mode or other
context defines it.

If the search finds no symbol with KEYMAP as its
value then the behavior is the same as if no search
was made (except for the time wasted on a failed
search): a symbol is generated for the map (just to
use the same code path).  The other difference is
that because you provided SEARCH-SYMBOLS-P you know
that a search turned up no symbol - more information.

> I admit that I find this code a bit hard to follow.  If I understand
> correctly, then most of this can be removed if we don't want to
> support SEARCH-SYMBOLS-P, and instead just require that the KEYMAP
> argument is a symbol.  Is that correct or am I missing something?

Who's "we"?  If a _user_ or calling code doesn't
want to search existing symbols then SEARCH-SYMBOLS-P
is supplied.  Nothing is lost by having it as a
behavior option, and something (quite a lot, actually)
is gained by making it available.  Putting a name on
a keymap object can be quite helpful.

The case where a user (or calling code) has a keymap
but no variable for it is not uncommon, even if it
is not the most common case.  Being able to find the
variable and see its doc is helpful.

> I'm sort of leaning towards simplifying this by removing the
> SEARCH-SYMBOLS-P argument, but I might not understand the use case
> here.  If I'm missing something, could you please briefly describe the
> use case for that and if and why it's important to keep?

See above.

> >   (let* ((name  (symbol-name keymap))
> >          (doc   (let ((raw-doc  (documentation-property keymap
> 'variable-documentation 'RAW)))
> >                   (substitute-command-keys raw-doc)))
>
> Why not just say (documentation-property keymap 'variable-
> documentation)
> without the 'RAW argument?  That should have the same effect as
> passing the 'RAW argument and then calling substitute-command-keys on
> the result, AFAICT.

Yes; sorry.  My code uses `help-documentation-property'
and `help-substitute-command-keys'.  I too quickly
substituted the body of `help-documentation-property',
changing its occurrence of `help-substitute-command-keys'
to just `substitute-command-keys'.  None of `h-d-p' is
needed here if you don't have `h-s-c-k'.

IOW, if neither of those is available then yes, all
you need is (documentation-property keymap
'variable-documentation).  Sorry about that mistake.

You might want to take a look at the full code,
in help-fns+.el, to see what the differences are.
Some are to support older Emacs versions too, others
are to provide additional features.

> > (doc   (and (not (equal "" doc))  doc)))
>
> Is this to allow us to simply say (when doc ...) below

Yes.  It makes DOC be either nil or real doc.

> instead of (when (not (equal "" doc)) ...)

[aka (unless (equal "" doc)...)]

No.  That's not the same.  That does `...' when doc
is nil.  The code should do `...' only when doc is
non-nil and not "".



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Stefan Kangas
Drew Adams <[hidden email]> writes:

> KEYMAP can be a keymap, instead of a symbol.

Thanks for the clarifications.

I've now packaged up a proposed patch with some cleanups and
adaptions.  It would be great if someone could review this.

Best regards,
Stefan Kangas

0001-Add-new-help-function-describe-keymap.patch (6K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Drew Adams
> I've now packaged up a proposed patch

Thanks for working on this.  Looks mostly OK to me.
However:

1. I object to the use of `C-h M' as the key binding.
   Please use `C-h M-k'.  The letter `M/m' has other,
   and more useful, associations (mode, mail, .  And
   `M' currently is translated to the often used
   `C-h m'.  `K' is often associated in Emacs with
   "key" or "kill".  And it's as easy to use Meta as
   it is to use Shift.

   [And users of `help-fns+.el', which has the same
   command but with additional features, are used to
   `C-h M-k'.  Because the vanilla version will lack
   those additional features I'll continue to maintain
   `describe-keymap' in `help-fns+.el'.  If those
   features are also added to vanilla Emacs someday
   then I won't need to maintain it.]

2. When testing with `emacs -Q' (but perhaps because
   I ran into the error of #3?), and also using
   `C-h f' etc., I somehow ended up with two [back]
   links at the bottom of *Help*, like this:

   [back]

   [back]

   Please check that what you end up with doesn't
   lead to this.

3. The code raises this error when KEYMAP is not a
   symbol and SEARCH-SYMBOLS-P is nil, because
   FILE-NAME is nil.

(describe-keymap isearch-mode-map) =>

Debugger entered--Lisp error: (wrong-type-argument stringp nil)
  file-name-nondirectory(nil)
  (if (eq file-name (quote C-source)) "C source code" (file-name-nondirectory file-name))
  ...

4. When fixing that bug, please be sure not to print
   a generated name ("KEYMAP OBJECT (no variable)")
   for a non-existent or not found variable.

5. When fixing that bug, if the keymap is fine, and
   it has a variable that is not defined in a file,
   don't try to print a file for it.  Don't try to
   print a file for the non-variable case either.

Wrt 3-5: It's not right to blindly print a variable
name and a file for it.  The code needs to handle
cases such as variable not given, no variable at all,
and variable not defined in a file.



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Lars Ingebrigtsen
In reply to this post by Stefan Kangas
Stefan Kangas <[hidden email]> writes:

> I've now packaged up a proposed patch with some cleanups and
> adaptions.  It would be great if someone could review this.

[...]

> This code was written by Drew Adams with minor cleanups and stylistic
> changes by Stefan Kangas.
> Ref: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30660
>
> * lisp/help-fns.el (describe-keymap): New function to show key
> bindings for a given keymap.  (Bug#30660)

This looks like a useful addition...

> * lisp/help.el (help-map): Bind the new function to "C-h M".
> * lisp/help.el (help-for-help-internal): Document what "C-h M" does
> when user types "C-h C-h".

`C-h m' is already used and `C-h M' auto-maps to it currently, so I'm
not sure that's the best binding.  But perhaps that's not a problem in
practice.

Other than that, I have no comments, and I think it should be applied to
Emacs 27.

--
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Eli Zaretskii
> From: Lars Ingebrigtsen <[hidden email]>
> Date: Mon, 14 Oct 2019 22:28:27 +0200
> Cc: [hidden email],
>  積丹尼 Dan Jacobson <[hidden email]>
>
> This looks like a useful addition...
>
> > * lisp/help.el (help-map): Bind the new function to "C-h M".
> > * lisp/help.el (help-for-help-internal): Document what "C-h M" does
> > when user types "C-h C-h".
>
> `C-h m' is already used and `C-h M' auto-maps to it currently, so I'm
> not sure that's the best binding.  But perhaps that's not a problem in
> practice.
>
> Other than that, I have no comments, and I think it should be applied to
> Emacs 27.

Fine with me, but let's not give it any key binding yet, and please
mention this command in NEWS.

Thanks.



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Drew Adams
In reply to this post by Lars Ingebrigtsen
> > * lisp/help.el (help-map): Bind the new function to "C-h M".
> > * lisp/help.el (help-for-help-internal): Document what "C-h M" does
> > when user types "C-h C-h".
>
> `C-h m' is already used and `C-h M' auto-maps to it currently, so I'm
> not sure that's the best binding.  But perhaps that's not a problem in
> practice.

I wrote the code for this command and have been using
it since 2007.

I already objected here two months ago to Emacs using
`C-h M' for this - in the message just after the one
you chose to reply to.

I requested that `C-h M-k' be used.  That's the key
I and others have been using for years.  And it's
mnemonic with "keymap" and "key".

Is there a good reason my input is just ignored?

For more info, including other problems with the
patch provided:

https://debbugs.gnu.org/cgi/bugreport.cgi?bug=30660#26

And I do suggest that the other features provided
in the original code be included in the vanilla
version as well.



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Stefan Kangas
In reply to this post by Drew Adams
Drew Adams <[hidden email]> writes:

> > I've now packaged up a proposed patch
>
> Thanks for working on this.  Looks mostly OK to me.
> However:

Thanks for the review.  I've fixed all your comments in a patch I'll send soon.

Best regards,
Stefan Kangas



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Stefan Kangas
In reply to this post by Drew Adams
Drew Adams <[hidden email]> writes:

> I requested that `C-h M-k' be used.

I'll add no keybinding at all, as Eli requested.

> Is there a good reason my input is just ignored?

I'm sorry if it looked like your input was being ignored.  I was busy
working on other things.

> And I do suggest that the other features provided
> in the original code be included in the vanilla
> version as well.

I'm not sure which features this refers to, but perhaps you could take
a look when I send the new patch and give your feedback.

Best regards,
Stefan Kangas



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Stefan Kangas
In reply to this post by Eli Zaretskii
Eli Zaretskii <[hidden email]> writes:

> Fine with me, but let's not give it any key binding yet, and please
> mention this command in NEWS.

Please find attached an updated patch fixing your comments as well as
earlier comments by Drew Adams.

In addition to adding this to NEWS, I've also updated the elisp manual.

Best regards,
Stefan Kangas

0001-Add-new-help-function-describe-keymap.patch (11K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Stefan Kangas
Stefan Kangas <[hidden email]> writes:

> Please find attached an updated patch fixing your comments as well as
> earlier comments by Drew Adams.
>
> In addition to adding this to NEWS, I've also updated the elisp manual.

Second try; I'd forgotten to remove some debug printouts from the tests.

Best regards,
Stefan Kangas

0001-Add-new-help-function-describe-keymap.patch (10K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Robert Pluim
>>>>> On Thu, 17 Oct 2019 11:42:25 +0200, Stefan Kangas <[hidden email]> said:

    Stefan> * lisp/help-fns.el (describe-keymap): New function to show key
    Stefan> bindings for a given keymap.  (Bug#30660)
    Stefan> * doc/lispref/keymaps.texi (Scanning Keymaps): Document it.
    Stefan> * etc/NEWS: Announce it.

    Stefan> * test/lisp/help-fns-tests.el (help-fns-test-describe-keymap/symbol)
    Stefan> (help-fns-test-describe-keymap/value)
    Stefan> (help-fns-test-describe-keymap/value+search-symbols)
    Stefan> (help-fns-test-describe-keymap/symbol+search-symbols)
    Stefan> (help-fns-test-describe-keymap/not-keymap)
    Stefan> (help-fns-test-describe-keymap/let-bound)
    Stefan> (help-fns-test-describe-keymap/dynamically-bound-no-file): New tests.
    Stefan> ---
    Stefan>  doc/lispref/keymaps.texi    | 12 ++++++
    Stefan>  etc/NEWS                    |  3 ++
    Stefan>  lisp/help-fns.el            | 73 +++++++++++++++++++++++++++++++++++++
    Stefan>  test/lisp/help-fns-tests.el | 41 +++++++++++++++++++++
    Stefan>  4 files changed, 129 insertions(+)

    Stefan> diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
    Stefan> index 532e537026..569e6137e6 100644
    Stefan> --- a/doc/lispref/keymaps.texi
    Stefan> +++ b/doc/lispref/keymaps.texi
    Stefan> @@ -2004,6 +2004,18 @@ Scanning Keymaps
    Stefan>  instead of the current buffer's.
    Stefan>  @end deffn
 
    Stefan> +@deffn Command describe-keymap keymap &optional search-symbols
    Stefan> +This function creates a listing of all key bindings in variable

s/variable//

    Stefan> +@var{keymap}, and displays it in a buffer named @file{*Help*}.  When
    Stefan> +called interactively, prompt for a variable that has a keymap value.
    Stefan> +
    Stefan> +If optional argument @var{search-symbols} is non-nil, and @var{keymap}
    Stefan> +is not a symbol, search all variables for one whose value is KEYMAP

@var{keymap}

Iʼm not clear on why it needs such a convoluted API, but I guess itʼs
useful to someone. Could the searching not be split into a
'find-keymap' function?

Robert



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Eli Zaretskii
In reply to this post by Stefan Kangas
> From: Stefan Kangas <[hidden email]>
> Date: Thu, 17 Oct 2019 11:39:31 +0200
> Cc: Lars Ingebrigtsen <[hidden email]>, [hidden email],
> 積丹尼 Dan Jacobson <[hidden email]>
>
> > Fine with me, but let's not give it any key binding yet, and please
> > mention this command in NEWS.
>
> Please find attached an updated patch fixing your comments as well as
> earlier comments by Drew Adams.
>
> In addition to adding this to NEWS, I've also updated the elisp manual.

Thanks.  However, I think that the right manual for this is the user
manual, not the ELisp manual.  It is, after all, a command whose
purpose is to show documentation to the user, right?

> Subject: [PATCH] Add new help function describe-keymap
>
> This code was written by Drew Adams.  Stefan Kangas adapted it for
> inclusion in Emacs, added unit tests and documentation.

I think CONTRIBUTE advises to use Co-authored-by for these situations.



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Eli Zaretskii
In reply to this post by Robert Pluim
> From: Robert Pluim <[hidden email]>
> Cc: Eli Zaretskii <[hidden email]>,  Lars Ingebrigtsen <[hidden email]>,
>   [hidden email],  積丹尼 Dan Jacobson
>  <[hidden email]>
> Date: Thu, 17 Oct 2019 14:07:10 +0200
>
> Iʼm not clear on why it needs such a convoluted API

Yes, I was wondering about that as well.  It looks somewhat artificial
to me.



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Stefan Kangas
Eli Zaretskii <[hidden email]> writes:

> > Iʼm not clear on why it needs such a convoluted API
>
> Yes, I was wondering about that as well.  It looks somewhat artificial
> to me.

I'd be happy to simplify it, but Drew felt that this was an important
use case.  Perhaps that could be covered by Robert Pluim's suggestion
to add a separate function 'find-keymap' instead.

Best regards,
Stefan Kangas



Reply | Threaded
Open this post in threaded view
|

bug#30660: mention describe-bindings on (info "(emacs) Keymaps")

Stefan Kangas
Stefan Kangas <[hidden email]> writes:

> Eli Zaretskii <[hidden email]> writes:
>
>> > Iʼm not clear on why it needs such a convoluted API
>>
>> Yes, I was wondering about that as well.  It looks somewhat artificial
>> to me.
>
> I'd be happy to simplify it, but Drew felt that this was an important
> use case.  Perhaps that could be covered by Robert Pluim's suggestion
> to add a separate function 'find-keymap' instead.
I've thought about this some more, and I think it's better to simplify
the API of 'describe-keymap'.  We could consider adding a separate
function 'find-keymap' later.

Please find attached a patch without the optional argument, and let me
know if there are any further comments.

Best regards,
Stefan Kangas


From 63952f2062d981c49d16e8643e287de00b19ffe3 Mon Sep 17 00:00:00 2001
From: Stefan Kangas <[hidden email]>
Date: Sat, 24 Aug 2019 01:02:04 +0200
Subject: [PATCH] Add new help command describe-keymap

* lisp/help-fns.el (describe-keymap): New command to show key bindings
for a given keymap.  (Bug#30660)
* doc/lispref/keymaps.texi (Scanning Keymaps): Document it.
* etc/NEWS: Announce it.

* test/lisp/help-fns-tests.el (help-fns-test-describe-keymap/symbol)
(help-fns-test-describe-keymap/value)
(help-fns-test-describe-keymap/not-keymap)
(help-fns-test-describe-keymap/let-bound)
(help-fns-test-describe-keymap/dynamically-bound-no-file): New tests.

Co-authored-by: Drew Adams <[hidden email]>
---
 doc/lispref/keymaps.texi    |  6 ++++
 etc/NEWS                    |  3 ++
 lisp/help-fns.el            | 59 +++++++++++++++++++++++++++++++++++++
 test/lisp/help-fns-tests.el | 29 ++++++++++++++++++
 4 files changed, 97 insertions(+)

diff --git a/doc/lispref/keymaps.texi b/doc/lispref/keymaps.texi
index 8ff329bdac..9fc0420b7e 100644
--- a/doc/lispref/keymaps.texi
+++ b/doc/lispref/keymaps.texi
@@ -2010,6 +2010,12 @@ Scanning Keymaps
 instead of the current buffer's.
 @end deffn
 
+@deffn Command describe-keymap keymap &optional search-symbols
+This function creates a listing of all key bindings in variable
+@var{keymap}, and displays it in a buffer named @file{*Help*}.  When
+called interactively, prompt for a variable that has a keymap value.
+@end deffn
+
 @node Menu Keymaps
 @section Menu Keymaps
 @cindex menu keymaps
diff --git a/etc/NEWS b/etc/NEWS
index 737053a099..cc98705cd3 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1443,6 +1443,9 @@ The maximum level is used by default; customize
 
 ** Help
 
++++
+*** New command 'describe-keymap' describes keybindings in a keymap.
+
 ---
 *** Description of variables and functions give an estimated first release.
 
diff --git a/lisp/help-fns.el b/lisp/help-fns.el
index 14dea7de9b..333eda0aac 100644
--- a/lisp/help-fns.el
+++ b/lisp/help-fns.el
@@ -1561,6 +1561,65 @@ describe-categories
   (insert "\nThe parent category table is:")
   (describe-vector table 'help-describe-category-set))))))
 
+;;;###autoload
+(defun describe-keymap (keymap)
+  "Describe key bindings in KEYMAP.
+When called interactively, prompt for a variable that has a
+keymap value."
+  (interactive (list
+                (intern (completing-read "Keymap: " obarray
+                                         (lambda (m)
+                                           (and (boundp m)
+                                                (keymapp (symbol-value m))))
+                                         t nil 'variable-name-history))))
+  (let (used-gentemp)
+    (unless (and (symbolp keymap)
+                 (boundp keymap)
+                 (keymapp (symbol-value keymap)))
+      (when (not (keymapp keymap))
+        (if (symbolp keymap)
+            (error "Not a keymap variable: %S" keymap)
+          (error "Not a keymap")))
+      (let ((sym nil))
+        (unless sym
+          (setq sym (cl-gentemp "KEYMAP OBJECT (no variable) "))
+          (setq used-gentemp t)
+          (set sym keymap))
+        (setq keymap sym)))
+    ;; Follow aliasing.
+    (setq keymap (or (ignore-errors (indirect-variable keymap)) keymap))
+    (help-setup-xref (list #'describe-keymap keymap)
+                     (called-interactively-p 'interactive))
+    (let* ((name (symbol-name keymap))
+           (doc (documentation-property keymap 'variable-documentation))
+           (file-name (find-lisp-object-file-name keymap 'defvar)))
+      (with-help-window (help-buffer)
+        (with-current-buffer standard-output
+          (unless used-gentemp
+            (princ (format-message "%S is a keymap variable" keymap))
+            (if (not file-name)
+                (princ ".\n\n")
+              (princ (format-message
+                      " defined in `%s'.\n\n"
+                      (if (eq file-name 'C-source)
+                          "C source code"
+                        (file-name-nondirectory file-name))))
+              (save-excursion
+                (re-search-backward (substitute-command-keys
+                                     "`\\([^`']+\\)'")
+                                    nil t)
+                (help-xref-button 1 'help-variable-def
+                                  keymap file-name))))
+          (when (and (not (equal "" doc)) doc)
+            (princ "Documentation:\n")
+            (princ (format-message "%s\n\n" doc)))
+          ;; Use `insert' instead of `princ', so control chars (e.g. \377)
+          ;; insert correctly.
+          (insert (substitute-command-keys (concat "\\{" name "}"))))))
+    ;; Cleanup.
+    (when used-gentemp
+      (makunbound keymap))))
+
 
 ;;; Replacements for old lib-src/ programs.  Don't seem especially useful.
 
diff --git a/test/lisp/help-fns-tests.el b/test/lisp/help-fns-tests.el
index da4d25d0a6..3921b59f2c 100644
--- a/test/lisp/help-fns-tests.el
+++ b/test/lisp/help-fns-tests.el
@@ -123,4 +123,33 @@ help-fns-test-describe-symbol
     (goto-char (point-min))
     (should (looking-at "^font-lock-comment-face is "))))
 
+
+
+;;; Tests for describe-keymap
+(ert-deftest help-fns-test-describe-keymap/symbol ()
+  (describe-keymap 'minibuffer-local-must-match-map)
+  (with-current-buffer "*Help*"
+    (should (looking-at "^minibuffer-local-must-match-map is"))))
+
+(ert-deftest help-fns-test-describe-keymap/value ()
+  (describe-keymap minibuffer-local-must-match-map)
+  (with-current-buffer "*Help*"
+    (should (looking-at "^key"))))
+
+(ert-deftest help-fns-test-describe-keymap/not-keymap ()
+  (should-error (describe-keymap nil))
+  (should-error (describe-keymap emacs-version)))
+
+(ert-deftest help-fns-test-describe-keymap/let-bound ()
+  (let ((foobar minibuffer-local-must-match-map))
+    (describe-keymap foobar)
+    (with-current-buffer "*Help*"
+      (should (looking-at "^key")))))
+
+(ert-deftest help-fns-test-describe-keymap/dynamically-bound-no-file ()
+  (setq help-fns-test--describe-keymap-foo minibuffer-local-must-match-map)
+  (describe-keymap 'help-fns-test--describe-keymap-foo)
+  (with-current-buffer "*Help*"
+    (should (looking-at "^help-fns-test--describe-keymap-foo is"))))
+
 ;;; help-fns-tests.el ends here
--
2.20.1

12