Reputation: 18075
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.
Upvotes: 5
Views: 4661
Reputation: 6197
I have just stumbled upon this myself and found that the Emacs defaults are actually fine by me.
By default, f10 is bound to menu-bar-open
and when I turn off the menu bar, it conveniently pops up a context menu. It doesn't show the actual menu bar on top, mind you, but I find this less disruptive because it doesn't "shift" the entire window around.
This doesn't work in terminal mode (emacs -nw
) for some reason. There, like you describe, when I type f10 I get the uglier tmm-menubar
and no amount of meddling with tty-menu-open-use-tmm
fixes that, regardless of what the menu bar documentation says. But that's in terminal mode, and you say you're in GUI mode.
Here's a screenshot of what I see in GUI mode (in the back) and TTY mode (in front):
So I'm not sure what's going on for you, but I've found that just erasing some of my customization helped a lot in this case, as is often the case with my aging Emacs configuration with a moving upstream... I also understand my answer is not exactly what you want
I'm using emacs-pgtk on Debian bookworm with the Emacs 29 backport.
Upvotes: 0
Reputation: 10950
I have tested this in GNU Emacs 25.2 and 26.3:
(menu-bar-mode -1)
(advice-add 'menu-bar-open
:around
(lambda (orig-fun &rest args)
(menu-bar-mode 1)
(apply orig-fun args)
(menu-bar-mode -1)))
Resulting behaviour (assuming that menu-bar-open
is bound to F10, which is the default):
Note that this is more like a hack than a proper solution.
Upvotes: 0
Reputation: 6114
In Emacs-24 you can simply do this:
(global-set-key [f9] 'toggle-menu-bar-mode-from-frame)
Upvotes: 9
Reputation: 21
A small improvement to Greg's answer, which keeps pre-command-hook
clean:
(menu-bar-mode -1)
(defun my-menu-bar-open-after ()
(remove-hook 'pre-command-hook 'my-menu-bar-open-after)
(when (eq menu-bar-mode 42)
(menu-bar-mode -1)))
(defun my-menu-bar-open (&rest args)
(interactive)
(let ((open menu-bar-mode))
(unless open
(menu-bar-mode 1))
(funcall 'menu-bar-open args)
(unless open
(setq menu-bar-mode 42)
(add-hook 'pre-command-hook 'my-menu-bar-open-after))))
(global-set-key [f10] 'my-menu-bar-open)
Upvotes: 2
Reputation: 2742
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
.
Upvotes: 4