emacs/var/elfeed/db/data/ca/ca86c615c2e17f6577551330a36da362535cbf96
2022-01-03 12:49:32 -06:00

89 lines
10 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.

<h2 id="org-mode-links">Org-mode links</h2>
<p>One of the many selling point of using Org-mode as a personal wiki (aka <em>digital garden</em>, see <a href="https://www.eigenbahn.com/2021/09/15/org-roam">previous post</a>) is its <a href="https://orgmode.org/manual/Hyperlinks.html"><em>(hyper)link</em> feature</a>.</p>
<p>As weve seen previously, we can define <em>internal</em> links between Org-file (and/or their outlines), but also <a href="https://orgmode.org/manual/External-Links.html"><em>external</em> links</a> targeting external files &amp; sytems. Those can either point to stuff openable in Emacs itself (e.g. link to files, to a shell command…) or external applications if configured as such (e.g. web pages).</p>
<h2 id="url-abbrevs">URL abbrevs</h2>
<p>Conveniently, pasted URL are directly resolved as <code class="language-plaintext highlighter-rouge">http(s)</code> links.</p>
<p>As usually, we may have a bunch of links to a few websites, it can be convenient to be able to have those in a shorter form.</p>
<p>Conveniently, Org-mode support <a href="https://orgmode.org/manual/Link-Abbreviations.html">link abbreviations</a>.</p>
<p>For example, we may define our list of recurrent linked website.</p>
<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="k">setq</span> <span class="nv">org-link-abbrev-alist</span> <span class="o">'</span><span class="p">((</span><span class="s">"gh"</span> <span class="o">.</span> <span class="s">"https://github.com/"</span><span class="p">)</span>
<span class="p">(</span><span class="s">"gl"</span> <span class="o">.</span> <span class="s">"https://gitlab.com/"</span><span class="p">)</span>
<span class="p">(</span><span class="s">"hn"</span> <span class="o">.</span> <span class="s">"https://news.ycombinator.com/item?id="</span><span class="p">)</span>
<span class="p">(</span><span class="s">"lines"</span> <span class="o">.</span> <span class="s">"https://llllllll.co/t/"</span><span class="p">)</span>
<span class="c1">;; [...]</span>
<span class="p">(</span><span class="s">"thing"</span> <span class="o">.</span> <span class="s">"https://www.thingiverse.com/thing:"</span><span class="p">)))</span>
</code></pre></div></div>
<p>One would just have to type <code class="language-plaintext highlighter-rouge">[[gh:emacs-mirror/emacs]]</code> instead of <code class="language-plaintext highlighter-rouge">https://github.com/emacs-mirror/emacs</code> to insert a link to Emacs github mirror.</p>
<h2 id="even-faster--shorter-url-abbrevs">Even faster &amp; shorter URL abbrevs</h2>
<p>The above solution is nice if we use <code class="language-plaintext highlighter-rouge">org-insert-link</code> to insert links.</p>
<p>But I personally find this command cumbersome. It prompts me 3 times (link type, actual link, description).</p>
<p>I want to go faster and just having to type <code class="language-plaintext highlighter-rouge">gh:emacs-mirror/emacs</code> to get a valid link.</p>
<p>One way to achieve this is to declare <a href="https://orgmode.org/manual/Adding-Hyperlink-Types.html">custom link types</a>.</p>
<p>The solution becomes:</p>
<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">require</span> <span class="ss">'dash</span><span class="p">)</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">my-org-link-abbrev-alist</span> <span class="o">'</span><span class="p">((</span><span class="s">"gh"</span> <span class="o">.</span> <span class="s">"https://github.com/"</span><span class="p">)</span>
<span class="c1">;; [...]</span>
<span class="p">(</span><span class="s">"thing"</span> <span class="o">.</span> <span class="s">"https://www.thingiverse.com/thing:"</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">--each</span> <span class="nv">my-org-link-abbrev-alist</span>
<span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">link-prefix</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">it</span><span class="p">))</span>
<span class="p">(</span><span class="nv">browse-fn</span> <span class="o">`</span><span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">e</span><span class="p">)</span>
<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">org-link-abbrev-alist</span> <span class="nv">my-org-link-abbrev-alist</span><span class="p">))</span>
<span class="p">(</span><span class="nv">browse-url</span> <span class="p">(</span><span class="nv">org-link-expand-abbrev</span> <span class="p">(</span><span class="nv">concat</span> <span class="o">,</span><span class="nv">link-prefix</span> <span class="s">":"</span> <span class="nv">e</span><span class="p">)))))))</span>
<span class="p">(</span><span class="nv">org-link-set-parameters</span> <span class="nv">link-prefix</span> <span class="ss">:follow</span> <span class="nv">browse-fn</span><span class="p">)))</span>
</code></pre></div></div>
<p>Please note that we renamed <code class="language-plaintext highlighter-rouge">org-link-abbrev-alist</code> to <code class="language-plaintext highlighter-rouge">my-org-link-abbrev-alist</code> to prevent having duplicated prefix entries if we ever want to call <code class="language-plaintext highlighter-rouge">org-insert-link</code>.</p>
<h2 id="auto-shortening-abbreved-links">Auto-shortening abbreved links</h2>
<p>Most of the time, I just copy/paste an URL into an Org buffer.</p>
<p>Wouldnt it be convenient if it would automagically shorten it if it correspond to a known abbrev?</p>
<p>Thankfully, this is relatively trivial by <em>advising</em> <code class="language-plaintext highlighter-rouge">org-yank</code>.</p>
<div class="language-elisp highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="nb">require</span> <span class="ss">'s</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">my-org-link-apply-prefix</span> <span class="p">(</span><span class="nv">txt</span><span class="p">)</span>
<span class="s">"Rework link TXT, swapping prefix w/ shorted one if matches `my-org-link-abbrev-alist'."</span>
<span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">prfx</span> <span class="p">(</span><span class="nv">--some</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nv">s-starts-with?</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">it</span><span class="p">)</span> <span class="nv">txt</span><span class="p">)</span> <span class="p">(</span><span class="nb">not</span> <span class="p">(</span><span class="nb">string=</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">it</span><span class="p">)</span> <span class="nv">txt</span><span class="p">))</span> <span class="nv">it</span><span class="p">)</span> <span class="nv">my-org-link-abbrev-alist</span><span class="p">)))</span>
<span class="p">(</span><span class="k">if</span> <span class="nv">prfx</span>
<span class="p">(</span><span class="nv">s-replace</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">prfx</span><span class="p">)</span> <span class="p">(</span><span class="nv">concat</span> <span class="p">(</span><span class="nb">car</span> <span class="nv">prfx</span><span class="p">)</span> <span class="s">":"</span><span class="p">)</span> <span class="nv">txt</span><span class="p">)</span>
<span class="nv">txt</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">defadvice</span> <span class="nv">org-yank</span> <span class="p">(</span><span class="nv">around</span> <span class="nv">prf/org-yank-prefix-link</span> <span class="nv">activate</span><span class="p">)</span>
<span class="s">"Advice around `org-yank' that will auto-compact current entry in `kill-ring' if it matches `my-org-link-abbrev-alist'."</span>
<span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">kill</span> <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nb">and</span> <span class="nv">kill-ring</span> <span class="p">(</span><span class="nv">current-kill</span> <span class="mi">0</span><span class="p">))</span> <span class="s">""</span><span class="p">))</span>
<span class="p">(</span><span class="nv">new-kill</span> <span class="p">(</span><span class="nv">my-org-link-apply-prefix</span> <span class="nv">kill</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nv">s-blank?</span> <span class="nv">new-kill</span><span class="p">)</span>
<span class="p">(</span><span class="nv">kill-new</span> <span class="nv">new-kill</span> <span class="no">t</span><span class="p">))</span>
<span class="nv">ad-do-it</span><span class="p">))</span>
</code></pre></div></div>
<p>Please not that <code class="language-plaintext highlighter-rouge">my-org-link-apply-prefix</code> only covers “basic” prefix abbrevs. It doesnt support formatted abbrevs (<code class="language-plaintext highlighter-rouge">%s</code>, <code class="language-plaintext highlighter-rouge">%h</code>) nor formatting using a custom function (<code class="language-plaintext highlighter-rouge">%(&lt;CUSTOM-FN&gt;)</code> for which wed need the inverse function).</p>
<h2 id="conclusion">Conclusion</h2>
<p>As always, this shows how flexible Emacs is and how expressive Elisp can be (once you are used to its quirks).</p>
<p>We showcased a very basic example of custom links. One could really go crazy with those.</p>
<p>For more in-depth examples, check out <a href="https://kitchingroup.cheme.cmu.edu/blog/2016/11/04/New-link-features-in-org-9/">this article</a> from the <em>The Kitchin Research Group</em> blog. They wrote <a href="https://kitchingroup.cheme.cmu.edu/blog/category/orgmode/">a bunch of advanced articles about Org</a>, notably about <em>Babel</em> (Orgs JupyterLab equivalent).</p>