notes from /dev/null

by Charles Choi 최민수


18 Jul 2025

Customizing the Emacs Help Menu

NGL, I’ve always found the default Emacs Help menu to be a bit too extra.

img

While the Help menu is commendable in trying to assist new users, I’ve long outgrown it as most of its offerings I can access via the keyboard. The Help menu though lacks a feature that I sorely miss from other apps: The ability to open a separate GUI window (in Emacs parlance, a frame) to read help in.

As always though with Emacs, you can customize nearly everything about it and that includes the Help menu which this post will cover. Readers are invited to adopt or adapt these customizations for their own. Consider this a followup to an earlier post of mine “Customizing the Emacs Tools Menu”.

A design challenge to building a menu for Emacs Help is that there are no less than four different help subsystems provided by it:

  • The Emacs Info reader for Texinfo files.
  • Elisp docstrings rendered by the describe- family of functions.
  • The Man page reader for troff formatted files.
  • shortdoc for an overview of functions relevant for a topic.

For my Help menu I’ve decided to make three ways to create a new frame:

  • Info in New Frame: Create a new frame with the Emacs Info reader.
  • New Info in New Frame: Create a new frame with a different Emacs Info reader instance. The user will be prompted for a manual to render.
  • Man Page in New Frame: Create a new frame with a Man page reader. The user will be prompted for a man page to render.

I’ve found the relatively recent addition of describe-symbol to generalize search of all docstrings to be a welcome one. Promoting it and describe-key to the first level of the menu seemed appropriate.

A recent TIL is the command finder-commentary which will display the commentary section of an Elisp library. I’ve found this command nice to have around but its name to be completely unmemorable, which makes it perfect to put in the menu labeled as “Library Commentary…”.

With existing Help menu items, I’ve decided to either remove or re-arrange them to taste. The result of my customizations looks like this:

img

Be forewarned, some Elisp ahead.

Implementation

To customize the Help menu it helps to know the internal key of a menu item. These keys are Elisp symbols. Here’s a utility function to help show these key symbols in string form:

1
2
3
4
5
6
(defun cc/show-global-map-keys (keypath)
  "Show formatted keys for keymap in `global-map' given KEYPATH."
  (interactive)
  (mapcar (lambda (x) (format "%s" x))
          (mapcar (lambda (x) (if (listp x) (car x)))
                  (cdr (lookup-key global-map keypath)))))

With cc/show-global-map-keys evaluated, we can run it in IELM as shown below for the keypath [menu-bar help-menu].

1
2
3
4
5
6
7
8
ELISP> (cc/show-global-map-keys [menu-bar help-menu])
("emacs-tutorial" "emacs-tutorial-language-specific" "emacs-faq"
 "emacs-news" "emacs-known-problems" "emacs-manual-bug"
 "send-emacs-bug-report" "emacs-psychotherapist" "sep1"
 "search-documentation" "describe" "emacs-manual" "more-manuals"
 "find-emacs-packages" "external-packages" "sep2"
 "getting-new-versions" "describe-copying" "describe-no-warranty"
 "sep4" "about-emacs" "about-gnu-project" "nil")

We’ll return back to these keys later.

Opening a new frame (aka GUI window) can be achieved with the function other-frame-prefix. We can wrap this function so that any interactive command can be invoked in a new frame as shown below.

1
2
3
4
5
(defun cc/--command-in-new-frame (cmd)
  "Invoke CMD in a new frame.
This command creates a new frame populated by CMD."
  (other-frame-prefix)
  (call-interactively cmd))

With cc/--command-in-new-frame in place, we can now add menu items using easy-menu-add-item. The next code example shows how to invoke info in a new frame as a menu item added before emacs-tutorial.

1
2
3
4
5
6
7
8
(easy-menu-add-item
 global-map '(menu-bar help-menu)
 ["Info in New Frame"
  (lambda ()
    (interactive)
    (cc/--command-in-new-frame #'info))
  :help "Show Info manual in new frame."]
 'emacs-tutorial)

Let’s add some more menu items to support viewing a Man page and for describe-symbol and describe-key. In addition, we’ll re-arrange some existing menu items by replicating their entry in global-map in a desired position and later deleting the older menu item with the same command.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
(easy-menu-add-item
 global-map '(menu-bar help-menu)
 ["New Info in New Frame…"
  (lambda ()
    (interactive)
    (cc/--command-in-new-frame #'info-display-manual))
  :help "Show new Info manual in new frame."]
 'emacs-tutorial)

(easy-menu-add-item
 global-map '(menu-bar help-menu)
 ["Man Page in New Frame…"
  (lambda ()
    (interactive)
    (cc/--command-in-new-frame #'man))
  :help "Show man page in new frame."]
 'emacs-tutorial)

(easy-menu-add-item
 global-map '(menu-bar help-menu)
 ["Describe Symbol…"
  describe-symbol
  :help "Describe symbol."]
 'emacs-tutorial)

(easy-menu-add-item
 global-map '(menu-bar help-menu)
 ["Describe Key or Mouse…"
  describe-key
  :help "Describe key or mouse operation."]
 'emacs-tutorial)

(easy-menu-add-item
 global-map '(menu-bar help-menu)
 ["Library Commentary…"
  finder-commentary
  :help "Show commentary for Elisp library."]
 'emacs-tutorial)

(easy-menu-add-item
 global-map '(menu-bar help-menu)
 ["Emacs FAQ"
  view-emacs-FAQ
  :help "View Emacs FAQ."]
 'describe-copying)

(easy-menu-add-item
 global-map '(menu-bar help-menu)
 ["Emacs News"
  view-emacs-news
  :help "View Emacs news about this release."]
 'describe-copying)

(easy-menu-add-item
 global-map '(menu-bar help-menu)
 ["Emacs Known Problems"
  view-emacs-problems
  :help "View Emacs known problems."]
 'describe-copying)

(easy-menu-add-item
 global-map '(menu-bar help-menu)
 ["Send Bug Report…"
  report-emacs-bug
  :help "Send Emacs bug report."]
 'describe-copying)

So far all we’ve done is add more menu items. Here’s how to get rid of the items using the keys obtained via cc/show-global-map-keys.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
(define-key global-map [menu-bar help-menu emacs-tutorial] nil t)
(define-key global-map [menu-bar help-menu emacs-tutorial-language-specific] nil t)
(define-key global-map [menu-bar help-menu emacs-psychotherapist] nil t)
(define-key global-map [menu-bar help-menu more-manuals] nil t)
(define-key global-map [menu-bar help-menu emacs-manual] nil t)
(define-key global-map [menu-bar help-menu getting-new-versions] nil t)
(define-key global-map [menu-bar help-menu describe-copying] nil t)
(define-key global-map [menu-bar help-menu describe-no-warranty] nil t)
(define-key global-map [menu-bar help-menu about-gnu-project] nil t)
(define-key global-map [menu-bar help-menu external-packages] nil t)
(define-key global-map [menu-bar help-menu emacs-faq] nil t)
(define-key global-map [menu-bar help-menu emacs-news] nil t)
(define-key global-map [menu-bar help-menu emacs-known-problems] nil t)
(define-key global-map [menu-bar help-menu emacs-manual-bug] nil t)
(define-key global-map [menu-bar help-menu send-emacs-bug-report] nil t)
(define-key global-map [menu-bar help-menu getting-new-versions] nil t)
(define-key global-map [menu-bar help-menu about-gnu-project] nil t)

Closing Thoughts

I’ve been living with this customized Help menu for several months now and upon reflection a couple of thoughts:

  • How did I live so long without this?

    Easy and non-disruptive access to Help in a separate GUI window is baseline for a proper application. Vanilla Emacs makes doing this way more onerous than need be:

    1. Create a new frame either from the menu “Edit › New Frame” or by recalling the arcane incantation C-x 5 2. (really?)
    2. Run M-x info in the new frame.

    With my reconfigured Help menu, I can just go to “Help › Info in New Frame” via mouse and it does the right thing without altering any existing Emacs window configuration. Simple pleasures.

  • To my surprise, I use Info so much more now.

    Having the Info reader in a separate GUI window lets me treat it like a web browser window but with the benefits of:

    1. Local access - never worry about a network connection.
    2. You’re still in Emacs.

    Couple that with my Casual interface for Info and I’d argue that Info is actually pleasurable to use. (Alongside that the same goes for Casual Man and Help.)

    Info is not exclusive to just Emacs manuals. You can read manuals for GNU coreutils, Make, Bash, Gnuplot, and many others. These days, whenever I’m dealing with software, I actively look to see if there’s Texinfo documentation for it.

If you’ve made it to here, thanks for reading!

emacs

Past Articles

8
JUL
2025

Capturing Org Source Blocks

Clip source code from your web browser elegantly with Org capture.

read more
2
JUL
2025

Capturing an Org note via macOS Shortcuts

Fun with macOS Shortcuts and Org protocol capture.

read more
30
JUN
2025

Take Two: Eshell

Don’t mistake Eshell as a drop-in replacement for a shell. It is so much more than that.

read more
24
JUN
2025

Announcing Casual Man & Help

Announcing Casual Man & Help, now available in Casual v2.6.0.

read more
2
JUN
2025

Announcing Casual Timezone

Always know what the time is, anywhere. Announcing Casual Timezone.

read more
8
MAY
2025

Opening the Emacs Initialization File, or First Impressions Matter

Opening the Emacs initialization file for new users is harder than it needs to be.

read more
28
APR
2025

Announcing Scrim - An Org Protocol Proxy for Emacs on macOS

Announcing Scrim, an Org Protocol proxy for Emacs on macOS.

read more
25
APR
2025

Sorting Strings in a Line in Emacs

Need to sort strings in a line? Emacs sort-regexp-fields to the rescue.

read more
14
APR
2025

Making an App, Looking for Beta Testers

Scrim is a macOS utility I've written to act as a proxy for Org Protocol requests. It is in BETA test and I’m looking for testers.

read more

Page 1 / 16   >

 

AboutMastodonBlueskyGitHub

Feeds & Tags
Get Scrim for macOSGet Captee for macOS

Powered by Pelican