It seems as though an irrational fear of the mouse dominates amongst Un*x dogmatists. Be it because their tools don’t integrate, or because it is a symbol or rebellion, a means to differentiate their prior ignorance from the enlightenment they have attained between the standard input and the standard output stream, the self-emancipation from the mouse is a rite of passage or a shameful burden on those who fail1 2.
As might be clear by my tone, I have little regard for this position. It certainly is worthwhile knowing that and how it is possible to avoid using the mouse, when keyboard shortcuts more convenient3, but there is no need for the artificial asceticism of ready-to-use technology, for the sake of purity and dogma.
The denunciation of the mouse usually involves invoking concepts such as the “home row”, or the cumbersome migration of the hand between keyboard and mouse. These might all be well and good, if I were a typist and as such all I did was to type. But this isn’t the case, I ponder and perceive, more than I write.
When debugging code or studying a program, it is quite comfortable to depend on only one hand, and have the other free to scribble or relax. The issue isn’t using a mouse or only using a keyboard, it is context switching.
And now for something mostly different: Speaking of “context”, here is something more concrete:
The more or less recent addition of
context-menu-mode by the ever creative Juri Linkov to Emacs 28 is worth talking about.
The general idea is to provide a “context menu” to Emacs, that can be invoked by a simple right click. You might know these kinds of menus from your file manager or browser, where you get fewer or more options, depend on what you clicked. To enabled this feature in Emacs 28 or greater, one simply has to enable the aforementioned
context-menu-mode minor mode.
It wouldn’t be Emacs if it ended here! It has to be configurable, extendable and improvable in accordance to the users needs and wants. That is where
context-menu-functions comes into play. This is a list of functions used to populate the menu programmatically. In my case, I set it to:
setq context-menu-functions ( '(context-menu-ffap occur-context-menu context-menu-region context-menu-undo context-menu-dictionary))
For example, the first function
context-menu-ffap checks if there is a generalized file name wherever I clicked, and in that case it will insert a menu item for me to open whatever I clicked on:
When first playing around with
context-menu-mode, my experiments led me to contribute
occur-context-menu that generates an occur buffer for the word or symbol at point. As mentioned, this is a nice instrument when debugging4.
I’d like to end with a few examples, demonstrating how to extend
context-menu-functions with your own functions:
By default this functionality is bound to
M-s h ., and I find it useful for debugging terse or complicated code. If we want to use the mouse instead, a
...-at-mouse command can be defined, together with a function placed in
context-menu-functions that adds entries to the menu using
defun highlight-symbol-at-mouse (e) ("Highlight symbol at mouse click E." "e") (interactive (save-excursion (mouse-set-point e) (highlight-symbol-at-point))) defun context-menu-highlight-symbol (menu click) ("Populate MENU with command to search online." (save-excursion (mouse-set-point click)when (symbol-at-point) ( (define-key-after menu [highlight-search-separator] menu-bar-separator) (define-key-after menu [highlight-search-mouse]"Highlight Symbol" highlight-symbol-at-mouse '(menu-item "Highlight symbol at point")))) :help menu) (add-hook 'context-menu-functions #'context-menu-highlight-symbol)
context-menu-highlight-symbol only adds
symbol-at-point indicates that there is a symbol that could be highlighted.
A popular feature from other text editors is to easily search for something online. The command
mouse-online-search-at-point implements something like this. As before, the command could be bound directly to some mouse key5, but to add it to the context menu we define another hook function:
require 'eww) ( defun mouse-online-search-at-point (e) ("Search for word at point or selection." "e") (interactive let ((query (if (region-active-p) ( (buffer-substring (region-beginning) (region-end)) (save-excursion (mouse-set-point e) (thing-at-point 'symbol)))))unless query ("Nothing to search for")) (user-error (browse-url (concat eww-search-prefix"+"))))) (mapconcat #'url-hexify-string (split-string query) defun context-menu-online-search (menu click) ("Populate MENU with command to search online." (save-excursion (mouse-set-point click) (define-key-after menu [online-search-separator] menu-bar-separator) (define-key-after menu [online-search-at-mouse]"Online search" mouse-online-search-at-point '(menu-item "Search for region or word online"))) :help menu)
eww-search-prefix to use a different search engine.
Another idea is to open man page, when clicking something like
emacs(1). This uses
man.el (but could just as well use
woman.el) to display the requested page.
defun man-at-mouse (e) ("Open man manual at point." "e") (interactive (save-excursion (mouse-set-point e) (man (Man-default-man-entry)))) defun man-context-menu (menu click) ("Populate MENU with commands that open a man page at point." (save-excursion (mouse-set-point click)when (save-excursion ("^ ") (skip-syntax-backward and (looking-at ("[[:space:]]*\([[:alnum:]_-]+([[:alnum:]]+)\)") 1))) (match-string (define-key-after menu [man-separator] menu-bar-separator) (define-key-after menu [man-at-mouse]"Open man page" man-at-mouse '(menu-item "Open man page around mouse click")))) :help menu) (add-hook 'context-menu-functions #'man-context-menu)
This could be extended to only offer displaying a man page, if it actually exists, and not just if something looks like a man page reference.
Emacs 28 has not yet been released, but pre-releases have been marked. If you want to try out this or other features, download the pre-release or clone the
emacs-28 branch of development repository to try it out, and report bugs if you find any!