Dynamically show/hide menu bar in Emacs

elisp, emacs, menu, menubar

Solution

If you're running a graphical Emacs session with `menu-bar-mode` disabled, then `C-<mouse-3>` should bring up the entire contents of the menu as a popup dialogue box. If you're running Emacs in a terminal, however, this definitely won't work; you haven't specified which is the case, so I'll try not to make assumptions. It's also possible to create custom mouse bindings (optionally, with keyboard modifiers) to the `mouse-popup-menubar` and/or `mouse-popup-menubar-stuff` functions, but ultimately that would only enable you to replicate behavior similar to the standard functionality that I've described above.

Due to the somewhat inflexible and global nature of `menu-bar-mode` (i.e., the fact that it applies across all Emacs frames and provides for relatively little customization via hooks, etc.), I think it would be very difficult to achieve precisely the behavior you desire with vanilla Emacs. It might be possible to write a custom function to temporarily enable `menu-bar-mode` and then use something like `post-command-hook` to disable it again after a selection is made, but I'm not certain. I'll try to investigate further if time allows.

Also, you might wish to look into third-party menu-bar packages, (q.v., the Menu Bar section of EmacsWiki).

Edit: I've hacked together a rather kludgy solution that you may find useful...

(add-hook
 'pre-command-hook
 (lambda ()
   (when (eq menu-bar-mode 42)
     (menu-bar-mode -1))))

(defun my-menu-bar-open ()
  (interactive)
  (unless menu-bar-mode
    (menu-bar-mode 1))
  (menu-bar-open)
  (setq menu-bar-mode 42))

I've tested this in a graphical session and it appears to simulate the behavior that you wanted, as long as you don't perform any action that Emacs registers as a command between executing `my-menu-bar-open` and making your selection (which is basically anything other than navigating the menu itself). The choice of `42` is a magic number (and a Douglas Adams homage) intended to minimize the risk that the hook function would be activated for more typical values of the `menu-bar-mode` variable. I don't claim that this is in any way elegant, but, in its decidedly ugly way, it does work. If you decide to use this, simply bind `my-menu-bar-open` to `f11` (or whatever you prefer), i.e.:

(global-set-key [f11] 'my-menu-bar-open)

Alternatively, you can probably achieve very similar functionality by using `pre-command-hook` in an analogous fashion and instead advising `menu-bar-open` to perform a temporary toggle of `menu-bar-mode`.

Problem

I have `menu-bar-open` bound on f11 and menu-bar turned off, and because of that, f11 calls `tmm-menubar`, which is inconvenient and doesn't have mode-specific menu items for some reason (like org and tbl in org-mode). I want it to behave this way: make menu-bar visible, enable user to choose menu item, after that make menu-bar invisible again. What is the most idiomatic and elegant way to to that? I thought on writing advices, but Emacs developers usually recommend against it, as it causes problems for debug, and standard Emacs code does not include advices. I use Emacs 24.1 in GUI.

Original source