emacs/var/elfeed/db/data/80/805a187231051d021ff85ae2d722f3cb8c76b209
2022-01-03 12:49:32 -06:00

110 lines
18 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<p>It seems as though an irrational fear of the <em>mouse</em> dominates amongst Un*x dogmatists. Be it because their tools dont integrate, or because it is a symbol or rebellion, a means to differentiate their prior ignorance from the enlightenment they have attained between the <em>standard input</em> and the <em>standard output</em> stream, the self-emancipation from the mouse is a rite of passage or a shameful burden on those who fail<a class="footnote-ref" href="https://ruzkuku.com/emacs.atom#fn1" id="fnref1"><sup>1</sup></a> <a class="footnote-ref" href="https://ruzkuku.com/emacs.atom#fn2" id="fnref2"><sup>2</sup></a>.</p>
<p>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 convenient<a class="footnote-ref" href="https://ruzkuku.com/emacs.atom#fn3" id="fnref3"><sup>3</sup></a>, but there is no need for the artificial asceticism of ready-to-use technology, for the sake of purity and dogma.</p>
<p>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 isnt the case, I ponder and perceive, more than I write.</p>
<p>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 isnt using a mouse or only using a keyboard, it is context switching.</p>
<hr />
<p>And now for something mostly different: Speaking of “context”, here is something more concrete:</p>
<p>The more or less recent addition of <code>context-menu-mode</code> by the ever creative <a href="https://jurta.org/en/emacs/">Juri Linkov</a> to Emacs 28 is worth talking about.</p>
<p>The general idea is to provide a <a href="https://en.wikipedia.org/wiki/Context_menu">“context menu”</a> 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 <code>context-menu-mode</code> minor mode.</p>
<p>It wouldnt 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 <code>context-menu-functions</code> comes into play. This is a list of functions used to populate the menu programmatically. In my case, I set it to:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb1-1"><a href="https://ruzkuku.com/emacs.atom#cb1-1" tabindex="-1"></a>(<span class="kw">setq</span> context-menu-functions</span>
<span id="cb1-2"><a href="https://ruzkuku.com/emacs.atom#cb1-2" tabindex="-1"></a> '(context-menu-ffap</span>
<span id="cb1-3"><a href="https://ruzkuku.com/emacs.atom#cb1-3" tabindex="-1"></a> occur-context-menu</span>
<span id="cb1-4"><a href="https://ruzkuku.com/emacs.atom#cb1-4" tabindex="-1"></a> context-menu-region</span>
<span id="cb1-5"><a href="https://ruzkuku.com/emacs.atom#cb1-5" tabindex="-1"></a> context-menu-undo</span>
<span id="cb1-6"><a href="https://ruzkuku.com/emacs.atom#cb1-6" tabindex="-1"></a> context-menu-dictionary))</span></code></pre></div>
<p>For example, the first function <code>context-menu-ffap</code> 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:</p>
<figure>
<img alt="An example of the context menu (keep in mind that the UI is specific to my Toolkit, to Emacs)" src="https://ruzkuku.com/images/emacs-context-menu.png" />An example of the context menu (keep in mind that the UI is specific to my Toolkit, to Emacs)
</figure>
<p>When first playing around with <code>context-menu-mode</code>, my experiments led me to <a href="https://git.savannah.gnu.org/cgit/emacs.git/commit/?id=3eb80b78473b425cdbc251e48aec7cfd9afea2cc">contribute</a> <code>occur-context-menu</code> that generates an occur buffer for the word or symbol at point. As mentioned, this is a nice instrument when debugging<a class="footnote-ref" href="https://ruzkuku.com/emacs.atom#fn4" id="fnref4"><sup>4</sup></a>.</p>
<p>Id like to end with a few examples, demonstrating how to extend <code>context-menu-functions</code> with your own functions:</p>
<h1 id="highlight-a-symbol-at-mouse">Highlight a symbol at mouse</h1>
<p>By default this functionality is bound to <code>M-s h .</code>, and I find it useful for debugging terse or complicated code. If we want to use the mouse instead, a <code>...-at-mouse</code> command can be defined, together with a function placed in <code>context-menu-functions</code> that adds entries to the menu using <code>define-key-after</code>:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb2-1"><a href="https://ruzkuku.com/emacs.atom#cb2-1" tabindex="-1"></a>(<span class="kw">defun</span><span class="fu"> highlight-symbol-at-mouse </span>(e)</span>
<span id="cb2-2"><a href="https://ruzkuku.com/emacs.atom#cb2-2" tabindex="-1"></a> <span class="st">"Highlight symbol at mouse click E."</span></span>
<span id="cb2-3"><a href="https://ruzkuku.com/emacs.atom#cb2-3" tabindex="-1"></a> (interactive <span class="st">"e"</span>)</span>
<span id="cb2-4"><a href="https://ruzkuku.com/emacs.atom#cb2-4" tabindex="-1"></a> (save-excursion</span>
<span id="cb2-5"><a href="https://ruzkuku.com/emacs.atom#cb2-5" tabindex="-1"></a> (mouse-set-point e)</span>
<span id="cb2-6"><a href="https://ruzkuku.com/emacs.atom#cb2-6" tabindex="-1"></a> (highlight-symbol-at-point)))</span>
<span id="cb2-7"><a href="https://ruzkuku.com/emacs.atom#cb2-7" tabindex="-1"></a></span>
<span id="cb2-8"><a href="https://ruzkuku.com/emacs.atom#cb2-8" tabindex="-1"></a>(<span class="kw">defun</span><span class="fu"> context-menu-highlight-symbol </span>(menu click)</span>
<span id="cb2-9"><a href="https://ruzkuku.com/emacs.atom#cb2-9" tabindex="-1"></a> <span class="st">"Populate MENU with command to search online."</span></span>
<span id="cb2-10"><a href="https://ruzkuku.com/emacs.atom#cb2-10" tabindex="-1"></a> (save-excursion</span>
<span id="cb2-11"><a href="https://ruzkuku.com/emacs.atom#cb2-11" tabindex="-1"></a> (mouse-set-point click)</span>
<span id="cb2-12"><a href="https://ruzkuku.com/emacs.atom#cb2-12" tabindex="-1"></a> (<span class="kw">when</span> (symbol-at-point)</span>
<span id="cb2-13"><a href="https://ruzkuku.com/emacs.atom#cb2-13" tabindex="-1"></a> (define-key-after menu [highlight-search-separator] menu-bar-separator)</span>
<span id="cb2-14"><a href="https://ruzkuku.com/emacs.atom#cb2-14" tabindex="-1"></a> (define-key-after menu [highlight-search-mouse]</span>
<span id="cb2-15"><a href="https://ruzkuku.com/emacs.atom#cb2-15" tabindex="-1"></a> '(menu-item <span class="st">"Highlight Symbol"</span> highlight-symbol-at-mouse</span>
<span id="cb2-16"><a href="https://ruzkuku.com/emacs.atom#cb2-16" tabindex="-1"></a> :help <span class="st">"Highlight symbol at point"</span>))))</span>
<span id="cb2-17"><a href="https://ruzkuku.com/emacs.atom#cb2-17" tabindex="-1"></a> menu)</span>
<span id="cb2-18"><a href="https://ruzkuku.com/emacs.atom#cb2-18" tabindex="-1"></a></span>
<span id="cb2-19"><a href="https://ruzkuku.com/emacs.atom#cb2-19" tabindex="-1"></a>(add-hook 'context-menu-functions #'context-menu-highlight-symbol)</span></code></pre></div>
<p>Notice how <code>context-menu-highlight-symbol</code> only adds <code>highlight-symbol-at-mouse</code> if <code>symbol-at-point</code> indicates that there is a symbol that could be highlighted.</p>
<h1 id="search-online">Search online</h1>
<p>A popular feature from other text editors is to easily search for something online. The command <code>mouse-online-search-at-point</code> implements something like this. As before, the command could be bound directly to some mouse key<a class="footnote-ref" href="https://ruzkuku.com/emacs.atom#fn5" id="fnref5"><sup>5</sup></a>, but to add it to the context menu we define another hook function:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb3-1"><a href="https://ruzkuku.com/emacs.atom#cb3-1" tabindex="-1"></a>(<span class="kw">require</span> 'eww)</span>
<span id="cb3-2"><a href="https://ruzkuku.com/emacs.atom#cb3-2" tabindex="-1"></a></span>
<span id="cb3-3"><a href="https://ruzkuku.com/emacs.atom#cb3-3" tabindex="-1"></a>(<span class="kw">defun</span><span class="fu"> mouse-online-search-at-point </span>(e)</span>
<span id="cb3-4"><a href="https://ruzkuku.com/emacs.atom#cb3-4" tabindex="-1"></a> <span class="st">"Search for word at point or selection."</span></span>
<span id="cb3-5"><a href="https://ruzkuku.com/emacs.atom#cb3-5" tabindex="-1"></a> (interactive <span class="st">"e"</span>)</span>
<span id="cb3-6"><a href="https://ruzkuku.com/emacs.atom#cb3-6" tabindex="-1"></a> (<span class="kw">let</span> ((query (<span class="kw">if</span> (use-region-p)</span>
<span id="cb3-7"><a href="https://ruzkuku.com/emacs.atom#cb3-7" tabindex="-1"></a> (buffer-substring (region-beginning)</span>
<span id="cb3-8"><a href="https://ruzkuku.com/emacs.atom#cb3-8" tabindex="-1"></a> (region-end))</span>
<span id="cb3-9"><a href="https://ruzkuku.com/emacs.atom#cb3-9" tabindex="-1"></a> (save-excursion</span>
<span id="cb3-10"><a href="https://ruzkuku.com/emacs.atom#cb3-10" tabindex="-1"></a> (mouse-set-point e)</span>
<span id="cb3-11"><a href="https://ruzkuku.com/emacs.atom#cb3-11" tabindex="-1"></a> (thing-at-point 'symbol)))))</span>
<span id="cb3-12"><a href="https://ruzkuku.com/emacs.atom#cb3-12" tabindex="-1"></a> (<span class="kw">unless</span> query</span>
<span id="cb3-13"><a href="https://ruzkuku.com/emacs.atom#cb3-13" tabindex="-1"></a> (user-error <span class="st">"Nothing to search for"</span>))</span>
<span id="cb3-14"><a href="https://ruzkuku.com/emacs.atom#cb3-14" tabindex="-1"></a> (browse-url (concat</span>
<span id="cb3-15"><a href="https://ruzkuku.com/emacs.atom#cb3-15" tabindex="-1"></a> eww-search-prefix</span>
<span id="cb3-16"><a href="https://ruzkuku.com/emacs.atom#cb3-16" tabindex="-1"></a> (mapconcat #'url-hexify-string (split-string query) <span class="st">"+"</span>)))))</span>
<span id="cb3-17"><a href="https://ruzkuku.com/emacs.atom#cb3-17" tabindex="-1"></a></span>
<span id="cb3-18"><a href="https://ruzkuku.com/emacs.atom#cb3-18" tabindex="-1"></a>(<span class="kw">defun</span><span class="fu"> context-menu-online-search </span>(menu click)</span>
<span id="cb3-19"><a href="https://ruzkuku.com/emacs.atom#cb3-19" tabindex="-1"></a> <span class="st">"Populate MENU with command to search online."</span></span>
<span id="cb3-20"><a href="https://ruzkuku.com/emacs.atom#cb3-20" tabindex="-1"></a> (save-excursion</span>
<span id="cb3-21"><a href="https://ruzkuku.com/emacs.atom#cb3-21" tabindex="-1"></a> (mouse-set-point click)</span>
<span id="cb3-22"><a href="https://ruzkuku.com/emacs.atom#cb3-22" tabindex="-1"></a> (define-key-after menu [online-search-separator] menu-bar-separator)</span>
<span id="cb3-23"><a href="https://ruzkuku.com/emacs.atom#cb3-23" tabindex="-1"></a> (define-key-after menu [online-search-at-mouse]</span>
<span id="cb3-24"><a href="https://ruzkuku.com/emacs.atom#cb3-24" tabindex="-1"></a> '(menu-item <span class="st">"Online search"</span> mouse-online-search-at-point</span>
<span id="cb3-25"><a href="https://ruzkuku.com/emacs.atom#cb3-25" tabindex="-1"></a> :help <span class="st">"Search for region or word online"</span>)))</span>
<span id="cb3-26"><a href="https://ruzkuku.com/emacs.atom#cb3-26" tabindex="-1"></a> menu)</span></code></pre></div>
<p>Modify <code>eww-search-prefix</code> to use a different search engine.</p>
<h1 id="open-a-man-page-at-mouse">Open a <code>man</code> page at mouse</h1>
<p>Another idea is to open man page, when clicking something like <code>emacs(1)</code>. This uses <code>man.el</code> (but could just as well use <code>woman.el</code>) to display the requested page.</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb4-1"><a href="https://ruzkuku.com/emacs.atom#cb4-1" tabindex="-1"></a>(<span class="kw">defun</span><span class="fu"> man-at-mouse </span>(e)</span>
<span id="cb4-2"><a href="https://ruzkuku.com/emacs.atom#cb4-2" tabindex="-1"></a> <span class="st">"Open man manual at point."</span></span>
<span id="cb4-3"><a href="https://ruzkuku.com/emacs.atom#cb4-3" tabindex="-1"></a> (interactive <span class="st">"e"</span>)</span>
<span id="cb4-4"><a href="https://ruzkuku.com/emacs.atom#cb4-4" tabindex="-1"></a> (save-excursion</span>
<span id="cb4-5"><a href="https://ruzkuku.com/emacs.atom#cb4-5" tabindex="-1"></a> (mouse-set-point e)</span>
<span id="cb4-6"><a href="https://ruzkuku.com/emacs.atom#cb4-6" tabindex="-1"></a> (man (Man-default-man-entry))))</span>
<span id="cb4-7"><a href="https://ruzkuku.com/emacs.atom#cb4-7" tabindex="-1"></a></span>
<span id="cb4-8"><a href="https://ruzkuku.com/emacs.atom#cb4-8" tabindex="-1"></a>(<span class="kw">defun</span><span class="fu"> man-context-menu </span>(menu click)</span>
<span id="cb4-9"><a href="https://ruzkuku.com/emacs.atom#cb4-9" tabindex="-1"></a> <span class="st">"Populate MENU with commands that open a man page at point."</span></span>
<span id="cb4-10"><a href="https://ruzkuku.com/emacs.atom#cb4-10" tabindex="-1"></a> (save-excursion</span>
<span id="cb4-11"><a href="https://ruzkuku.com/emacs.atom#cb4-11" tabindex="-1"></a> (mouse-set-point click)</span>
<span id="cb4-12"><a href="https://ruzkuku.com/emacs.atom#cb4-12" tabindex="-1"></a> (<span class="kw">when</span> (save-excursion</span>
<span id="cb4-13"><a href="https://ruzkuku.com/emacs.atom#cb4-13" tabindex="-1"></a> (skip-syntax-backward <span class="st">"^ "</span>)</span>
<span id="cb4-14"><a href="https://ruzkuku.com/emacs.atom#cb4-14" tabindex="-1"></a> (<span class="kw">and</span> (looking-at</span>
<span id="cb4-15"><a href="https://ruzkuku.com/emacs.atom#cb4-15" tabindex="-1"></a> <span class="st">"[[:space:]]*</span><span class="sc">\\</span><span class="st">([[:alnum:]_-]+([[:alnum:]]+)</span><span class="sc">\\</span><span class="st">)"</span>)</span>
<span id="cb4-16"><a href="https://ruzkuku.com/emacs.atom#cb4-16" tabindex="-1"></a> (match-string <span class="dv">1</span>)))</span>
<span id="cb4-17"><a href="https://ruzkuku.com/emacs.atom#cb4-17" tabindex="-1"></a> (define-key-after menu [man-separator] menu-bar-separator)</span>
<span id="cb4-18"><a href="https://ruzkuku.com/emacs.atom#cb4-18" tabindex="-1"></a> (define-key-after menu [man-at-mouse]</span>
<span id="cb4-19"><a href="https://ruzkuku.com/emacs.atom#cb4-19" tabindex="-1"></a> '(menu-item <span class="st">"Open man page"</span> man-at-mouse</span>
<span id="cb4-20"><a href="https://ruzkuku.com/emacs.atom#cb4-20" tabindex="-1"></a> :help <span class="st">"Open man page around mouse click"</span>))))</span>
<span id="cb4-21"><a href="https://ruzkuku.com/emacs.atom#cb4-21" tabindex="-1"></a> menu)</span>
<span id="cb4-22"><a href="https://ruzkuku.com/emacs.atom#cb4-22" tabindex="-1"></a></span>
<span id="cb4-23"><a href="https://ruzkuku.com/emacs.atom#cb4-23" tabindex="-1"></a>(add-hook 'context-menu-functions #'man-context-menu)</span></code></pre></div>
<p>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.</p>
<hr />
<p>Emacs 28 has not yet been released, but pre-releases have been marked. If you want to try out this or other features, <a href="https://git.savannah.gnu.org/cgit/emacs.git/tree/INSTALL">download</a> the pre-release or clone the <code>emacs-28</code> branch of development repository to try it out, and <a href="https://www.gnu.org/software/emacs/manual/html_node/efaq/Reporting-bugs.html">report bugs</a> if you find any!</p>
<section class="footnotes">
<hr />
<ol>
<li id="fn1"><p>Interestingly enough it comes as a shock to many when it is discovered that <a href="http://9p.io/plan9/">Plan 9</a> rejects this apparent commandment, to shun the mouse<a class="footnote-back" href="https://ruzkuku.com/emacs.atom#fnref1">↩︎</a></p></li>
<li id="fn2"><p>I am not a philosopher, so I might be applying the wrong concepts here, but there seems to be a bit of Nietzsches <a href="https://en.wikipedia.org/wiki/Master%E2%80%93slave_morality#Slave_morality">“inversion of values”</a> playing here, where the limitations one suffers are turned into virtues, and vice versa.<a class="footnote-back" href="https://ruzkuku.com/emacs.atom#fnref2">↩︎</a></p></li>
<li id="fn3"><p>That is to say that they are, in fact, <em>short</em>-cuts.<a class="footnote-back" href="https://ruzkuku.com/emacs.atom#fnref3">↩︎</a></p></li>
<li id="fn4"><p>As seen above, in programming modes <code>context-menu-mode</code> also integrates with xref<a class="footnote-back" href="https://ruzkuku.com/emacs.atom#fnref4">↩︎</a></p></li>
<li id="fn5"><p>Eg. this would call the command whenever the command key is pressed and the user double clicks: <code>(global-set-key (kbd "C-&lt;double-mouse-1&gt;") #'mouse-online-search-at-point)</code>.<a class="footnote-back" href="https://ruzkuku.com/emacs.atom#fnref5">↩︎</a></p></li>
</ol>
</section>