<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-us"><generator uri="https://gohugo.io/" version="0.101.0">Hugo</generator><title type="html">search on A Scripter's Notes</title><subtitle type="html">Emacs, scripting and anything text oriented.</subtitle><link href="https://scripter.co/tags/search/" rel="alternate" type="text/html" title="HTML"/><link href="https://scripter.co/tags/search/index.xml" rel="alternate" type="application/rss+xml" title="RSS"/><link href="https://scripter.co/tags/search/atom.xml" rel="self" type="application/atom+xml" title="Atom"/><link href="https://scripter.co/tags/search/jf2feed.json" rel="alternate" type="application/jf2feed+json" title="jf2feed"/><updated>2024-01-08T07:42:20-05:00</updated><author><name>Kaushal Modi</name><email>kaushal.modi@gmail.com</email></author><id>https://scripter.co/tags/search/</id><entry><title type="html">Accessing Devdocs from Emacs</title><link href="https://scripter.co/accessing-devdocs-from-emacs/?utm_source=atom_feed" rel="alternate" type="text/html"/><link href="https://scripter.co/notes/string-fns-nim-vs-python/?utm_source=atom_feed" rel="related" type="text/html" title="String Functions: Nim vs Python"/><id>https://scripter.co/accessing-devdocs-from-emacs/</id><author><name>Kaushal Modi</name></author><published>2018-05-10T12:45:00-04:00</published><updated>2021-12-17T00:00:00-05:00</updated><content type="html"><![CDATA[<blockquote>Spoiled by being able to access in-built docs in Emacs at fingertips,
here&rsquo;s an attempt to <em>kind-of</em> do that for Nim documentation too,
using <code>devdocs.io</code>.</blockquote><div class="ox-hugo-toc toc">
<div class="heading">Table of Contents</div>
<ul>
<li><a href="#json-docs">JSON Docs</a></li>
<li><a href="#devdocs-dot-io">Devdocs.io</a>
<ul>
<li><a href="#christopher-wellon-s-devdocs-lookup">Christopher Wellon&rsquo;s <code>devdocs-lookup</code></a></li>
<li><a href="#making-devdocs-lookup-dwim">Making <code>devdocs-lookup</code> DWIM</a></li>
</ul>
</li>
<li><a href="#using-devdocs-lookup">Using <code>devdocs-lookup</code></a></li>
<li><a href="#devdocs-lookup-demo">Demo</a></li>
<li><a href="#devdocs-lookup-code">Code</a></li>
</ul>
</div>
<!--endtoc-->
<p>Nim lang has good documentation for all its <code>stdlib</code> functions
<a href="https://nim-lang.org/docs/lib.html">online</a>. But the Emacs user in me does not like to switch back and
forth between the Nim code in Emacs buffers and the docs outside in an
external browser.</p>
<p>Well.. a solution to that, that this post is about, <em>still</em> needs one
to look up the Nim docs in an external browser.. but the workflow is a
bit better &mdash; You don&rsquo;t need to manually launch the doc site, and you
don&rsquo;t need to then manually type in the search query.</p>
<div class="note">
<p>If you want to skip the history and code analysis, you can directly
jump to the <a href="#devdocs-lookup-demo">Demo</a> or the <a href="#devdocs-lookup-code">Final Code</a>.</p>
</div>

<h2 id="json-docs">JSON Docs&nbsp;<a class="headline-hash no-text-decoration" href="#json-docs">#</a></h2>


<p>I tried asking folks on <a href="https://www.reddit.com/r/nim/comments/8ia1xk/is_there_a_way_to_access_the_nim_docs_from_the/">r/nim</a> if there was a good solution for
<em>in-editor</em> Nim doc access. <a href="https://www.reddit.com/user/PMunch"><strong>/u/PMunch</strong></a> from Reddit gave a wonderful
<a href="https://www.reddit.com/r/nim/comments/8ia1xk/is_there_a_way_to_access_the_nim_docs_from_the/dyqcb2m/">solution</a>&mdash;To generate JSON docs for the Nim stdlib, and then parse
those to display the docs within Emacs.</p>
<div class="verse">
<p>    I would love that solution!<br /></p>
</div>
<p>.. just that I don&rsquo;t know how to get a nice single <code>.json</code> for the
whole of Nim documentation.</p>
<p><em>If someone knows how to do that, please let me know.</em></p>

<h2 id="devdocs-dot-io">Devdocs.io&nbsp;<a class="headline-hash no-text-decoration" href="#devdocs-dot-io">#</a></h2>


<p>So I continued my search online.. I was looking if someone had already
implemented a way to access Nim docs from the command line, and that
somehow led me to <a href="https://devdocs.io/nim/">https://devdocs.io/nim/</a>!</p>
<p>And after searching further for <em>&ldquo;devdocs Emacs&rdquo;</em>, I found these two
Emacs packages:</p>
<ul>
<li><a href="https://github.com/xuchunyang/DevDocs.el">https://github.com/xuchunyang/DevDocs.el</a></li>
<li><a href="https://github.com/skeeto/devdocs-lookup">https://github.com/skeeto/devdocs-lookup</a></li>
</ul>

<h3 id="christopher-wellon-s-devdocs-lookup">Christopher Wellon&rsquo;s <code>devdocs-lookup</code>&nbsp;<a class="headline-hash no-text-decoration" href="#christopher-wellon-s-devdocs-lookup">#</a></h3>


<p>After reviewing the two packages, I decided to build my solution
further upon the <code>devdocs-lookup</code> package<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> by <em>Christopher
Wellons</em> aka <a href="https://www.github.com/skeeto"><strong>@skeeto</strong></a> from GitHub.</p>
<p>Here&rsquo;s why &mdash;</p>
<ol>
<li>
<p>He first fetches the whole JSON <em>search index</em> (<a href="#org-coderef--e4865e-5">line 5</a>) from
docs.devdocs.io for the picked &ldquo;subject&rdquo; (which would be &ldquo;Nim&rdquo; for
this post). So the search index for Nim documentation would be at
<a href="https://docs.devdocs.io/nim/index.json">https://docs.devdocs.io/nim/index.json</a><sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>.</p>
<p>The retrieved JSON is then parsed using <code>json-read</code> (<a href="#org-coderef--e4865e-13">line
13</a>).
<a id="code-snippet--devdocs-index"></a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt" id="org-coderef--e4865e-1"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-1"> 1</a>
</span><span class="lnt" id="org-coderef--e4865e-2"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-2"> 2</a>
</span><span class="lnt" id="org-coderef--e4865e-3"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-3"> 3</a>
</span><span class="lnt" id="org-coderef--e4865e-4"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-4"> 4</a>
</span><span class="hl"><span class="lnt" id="org-coderef--e4865e-5"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-5"> 5</a>
</span></span><span class="lnt" id="org-coderef--e4865e-6"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-6"> 6</a>
</span><span class="lnt" id="org-coderef--e4865e-7"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-7"> 7</a>
</span><span class="lnt" id="org-coderef--e4865e-8"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-8"> 8</a>
</span><span class="lnt" id="org-coderef--e4865e-9"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-9"> 9</a>
</span><span class="lnt" id="org-coderef--e4865e-10"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-10">10</a>
</span><span class="lnt" id="org-coderef--e4865e-11"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-11">11</a>
</span><span class="lnt" id="org-coderef--e4865e-12"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-12">12</a>
</span><span class="hl"><span class="lnt" id="org-coderef--e4865e-13"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-13">13</a>
</span></span><span class="lnt" id="org-coderef--e4865e-14"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-14">14</a>
</span><span class="lnt" id="org-coderef--e4865e-15"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-15">15</a>
</span><span class="lnt" id="org-coderef--e4865e-16"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-16">16</a>
</span><span class="lnt" id="org-coderef--e4865e-17"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-17">17</a>
</span><span class="lnt" id="org-coderef--e4865e-18"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-18">18</a>
</span><span class="lnt" id="org-coderef--e4865e-19"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-19">19</a>
</span><span class="lnt" id="org-coderef--e4865e-20"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e4865e-20">20</a>
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">devdocs-index</span> <span class="p">(</span><span class="nv">subject</span> <span class="kp">&amp;optional</span> <span class="nv">callback</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Return the devdocs.io index for SUBJECT, optionally async via CALLBACK.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">cl-declare</span> <span class="p">(</span><span class="nv">special</span> <span class="nv">url-http-end-of-headers</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">index</span> <span class="p">(</span><span class="nf">gethash</span> <span class="nv">subject</span> <span class="nv">devdocs-index</span><span class="p">))</span>
</span></span><span class="line hl"><span class="cl">        <span class="p">(</span><span class="nv">url</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;%s/%s/index.json&#34;</span> <span class="nv">devdocs-base-index-url</span> <span class="nv">subject</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">cond</span> <span class="p">((</span><span class="nb">and</span> <span class="nv">index</span> <span class="nv">callback</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nf">funcall</span> <span class="nv">callback</span> <span class="nv">index</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">          <span class="p">((</span><span class="nb">and</span> <span class="nv">index</span> <span class="p">(</span><span class="nv">not</span> <span class="nv">callback</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">           <span class="nv">index</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">          <span class="p">((</span><span class="nb">and</span> <span class="p">(</span><span class="nv">not</span> <span class="nv">index</span><span class="p">)</span> <span class="p">(</span><span class="nv">not</span> <span class="nv">callback</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nb">with-current-buffer</span> <span class="p">(</span><span class="nv">url-retrieve-synchronously</span> <span class="nv">url</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">             <span class="p">(</span><span class="nf">goto-char</span> <span class="nv">url-http-end-of-headers</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl">             <span class="p">(</span><span class="nb">setf</span> <span class="p">(</span><span class="nf">gethash</span> <span class="nv">subject</span> <span class="nv">devdocs-index</span><span class="p">)</span> <span class="p">(</span><span class="nv">json-read</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">          <span class="p">((</span><span class="nb">and</span> <span class="p">(</span><span class="nv">not</span> <span class="nv">index</span><span class="p">)</span> <span class="nv">callback</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">           <span class="p">(</span><span class="nv">url-retrieve</span>
</span></span><span class="line"><span class="cl">            <span class="nv">url</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nb">lambda</span> <span class="p">(</span><span class="nv">_</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">              <span class="p">(</span><span class="nf">goto-char</span> <span class="nv">url-http-end-of-headers</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">              <span class="p">(</span><span class="nb">setf</span> <span class="p">(</span><span class="nf">gethash</span> <span class="nv">subject</span> <span class="nv">devdocs-index</span><span class="p">)</span> <span class="p">(</span><span class="nv">json-read</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">              <span class="p">(</span><span class="nf">funcall</span> <span class="nv">callback</span> <span class="p">(</span><span class="nf">gethash</span> <span class="nv">subject</span> <span class="nv">devdocs-index</span><span class="p">))))))))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="src-block-caption">
  <span class="src-block-number"><a href="#code-snippet--devdocs-index">Code Snippet 1</a>:</span>
  Function to fetch the search index from devdocs.io and parse the JSON
</div>
</li>
<li>
<p>The <code>name</code> and <code>path</code> properties from the parsed JSON are then
stored in an association list on lines <a href="#org-coderef--6fba6a-4">4</a> and <a href="#org-coderef--6fba6a-5">5</a>.
<a id="code-snippet--devdocs-entries"></a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt" id="org-coderef--6fba6a-1"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--6fba6a-1">1</a>
</span><span class="lnt" id="org-coderef--6fba6a-2"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--6fba6a-2">2</a>
</span><span class="lnt" id="org-coderef--6fba6a-3"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--6fba6a-3">3</a>
</span><span class="hl"><span class="lnt" id="org-coderef--6fba6a-4"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--6fba6a-4">4</a>
</span></span><span class="hl"><span class="lnt" id="org-coderef--6fba6a-5"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--6fba6a-5">5</a>
</span></span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">devdocs-entries</span> <span class="p">(</span><span class="nv">subject</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Return an association list of the entries in SUBJECT.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">cl-loop</span> <span class="nv">for</span> <span class="nv">entry</span> <span class="nv">across</span> <span class="p">(</span><span class="nf">cdr</span> <span class="p">(</span><span class="nf">assoc</span> <span class="ss">&#39;entries</span> <span class="p">(</span><span class="nv">devdocs-index</span> <span class="nv">subject</span><span class="p">)))</span>
</span></span><span class="line hl"><span class="cl">           <span class="nv">collect</span> <span class="p">(</span><span class="nf">cons</span> <span class="p">(</span><span class="nf">cdr</span> <span class="p">(</span><span class="nf">assoc</span> <span class="ss">&#39;name</span> <span class="nv">entry</span><span class="p">))</span>
</span></span><span class="line hl"><span class="cl">                         <span class="p">(</span><span class="nf">cdr</span> <span class="p">(</span><span class="nf">assoc</span> <span class="ss">&#39;path</span> <span class="nv">entry</span><span class="p">)))))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="src-block-caption">
  <span class="src-block-number"><a href="#code-snippet--devdocs-entries">Code Snippet 2</a>:</span>
  Function to store the <code>name</code> and <code>path</code> properties to alists
</div>
<p>So a JSON entry like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;name&#34;</span><span class="p">:</span> <span class="s2">&#34;os.walkDirRec&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;path&#34;</span><span class="p">:</span> <span class="s2">&#34;os#walkDirRec.i,string&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;type&#34;</span><span class="p">:</span> <span class="s2">&#34;os&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>would translate to this Emacs-Lisp alist element:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="s">&#34;os.walkDirRec&#34;</span> <span class="o">.</span> <span class="s">&#34;os#walkDirRec.i,string&#34;</span><span class="p">)</span>
</span></span></code></pre></div></li>
<li>
<p>Then the <em>list</em> of all the <em>car</em>&rsquo;s of such elements is used to
create a collection of entries for completion (<a href="#org-coderef--25a1bb-3">line 3</a>).
<a id="code-snippet--devdocs-read-entry"></a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt" id="org-coderef--25a1bb-1"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--25a1bb-1">1</a>
</span><span class="lnt" id="org-coderef--25a1bb-2"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--25a1bb-2">2</a>
</span><span class="hl"><span class="lnt" id="org-coderef--25a1bb-3"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--25a1bb-3">3</a>
</span></span><span class="lnt" id="org-coderef--25a1bb-4"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--25a1bb-4">4</a>
</span><span class="lnt" id="org-coderef--25a1bb-5"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--25a1bb-5">5</a>
</span><span class="lnt" id="org-coderef--25a1bb-6"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--25a1bb-6">6</a>
</span><span class="lnt" id="org-coderef--25a1bb-7"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--25a1bb-7">7</a>
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">devdocs-read-entry</span> <span class="p">(</span><span class="nv">subject</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Interactively ask the user for an entry in SUBJECT.&#34;</span>
</span></span><span class="line hl"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">names</span> <span class="p">(</span><span class="nf">mapcar</span> <span class="nf">#&#39;car</span> <span class="p">(</span><span class="nv">devdocs-entries</span> <span class="nv">subject</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">hist</span> <span class="p">(</span><span class="nf">intern</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;devdocs--hist-%s&#34;</span> <span class="nv">subject</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nf">boundp</span> <span class="nv">hist</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">set</span> <span class="nv">hist</span> <span class="no">nil</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nf">completing-read</span> <span class="s">&#34;Entry: &#34;</span> <span class="nv">names</span> <span class="no">nil</span> <span class="nb">:match</span> <span class="no">nil</span> <span class="nv">hist</span><span class="p">)))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="src-block-caption">
  <span class="src-block-number"><a href="#code-snippet--devdocs-read-entry">Code Snippet 3</a>:</span>
  Function to show completion list based on "names" from the JSON-parsed database
</div>
</li>
<li>
<p>And finally, for the selected <em>name</em>, the associated <em>path</em> is
retrieved from that <em>alist</em> (<a href="#org-coderef--e484ad-7">line 7</a>), and we browse
to that path using the Emacs <code>browse-url</code> function (<a href="#org-coderef--e484ad-9">line
9</a>). <em>User can of course configure the browser to be used
when that function is called.</em>
<a id="code-snippet--devdocs-lookup"></a></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt" id="org-coderef--e484ad-1"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e484ad-1"> 1</a>
</span><span class="lnt" id="org-coderef--e484ad-2"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e484ad-2"> 2</a>
</span><span class="lnt" id="org-coderef--e484ad-3"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e484ad-3"> 3</a>
</span><span class="lnt" id="org-coderef--e484ad-4"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e484ad-4"> 4</a>
</span><span class="lnt" id="org-coderef--e484ad-5"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e484ad-5"> 5</a>
</span><span class="lnt" id="org-coderef--e484ad-6"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e484ad-6"> 6</a>
</span><span class="hl"><span class="lnt" id="org-coderef--e484ad-7"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e484ad-7"> 7</a>
</span></span><span class="lnt" id="org-coderef--e484ad-8"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e484ad-8"> 8</a>
</span><span class="hl"><span class="lnt" id="org-coderef--e484ad-9"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e484ad-9"> 9</a>
</span></span><span class="lnt" id="org-coderef--e484ad-10"><a style="outline: none; text-decoration:none; color:inherit" href="#org-coderef--e484ad-10">10</a>
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">devdocs-lookup</span> <span class="p">(</span><span class="nv">subject</span> <span class="nv">entry</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Visit the documentation for ENTRY from SUBJECT in a browser.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span>
</span></span><span class="line"><span class="cl">   <span class="p">(</span><span class="nb">let*</span> <span class="p">((</span><span class="nv">subject</span> <span class="p">(</span><span class="nv">devdocs-read-subject</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">          <span class="p">(</span><span class="nv">entry</span> <span class="p">(</span><span class="nv">devdocs-read-entry</span> <span class="nv">subject</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">     <span class="p">(</span><span class="nf">list</span> <span class="nv">subject</span> <span class="nv">entry</span><span class="p">)))</span>
</span></span><span class="line hl"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">path</span> <span class="p">(</span><span class="nf">cdr</span> <span class="p">(</span><span class="nf">assoc</span> <span class="nv">entry</span> <span class="p">(</span><span class="nv">devdocs-entries</span> <span class="nv">subject</span><span class="p">)))))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">when</span> <span class="nv">path</span>
</span></span><span class="line hl"><span class="cl">      <span class="p">(</span><span class="nv">browse-url</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;%s/%s/%s&#34;</span> <span class="nv">devdocs-base-url</span> <span class="nv">subject</span> <span class="nv">path</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="nb">:found</span><span class="p">)))</span>
</span></span></code></pre></td></tr></table>
</div>
</div><div class="src-block-caption">
  <span class="src-block-number"><a href="#code-snippet--devdocs-lookup">Code Snippet 4</a>:</span>
  Function to browse the doc page associated with the user-selected "name"
</div>
</li>
</ol>
<p>All of that worked beautifully. As I used it a few times though, I
felt a need to add a touch of <abbr aria-label="Do What I Mean" tabindex=0>DWIM</abbr> to that.</p>

<h3 id="making-devdocs-lookup-dwim">Making <code>devdocs-lookup</code> DWIM&nbsp;<a class="headline-hash no-text-decoration" href="#making-devdocs-lookup-dwim">#</a></h3>


<p>Here are the 2 things that I wanted to happen automatically:</p>

<h4 id="auto-select-subject-based-on-major-mode-if-possible">Auto-select subject based on <code>major-mode</code> if possible&nbsp;<a class="headline-hash no-text-decoration" href="#auto-select-subject-based-on-major-mode-if-possible">#</a></h4>


<p>In the original code, if I used <code>devdocs-lookup</code> function, I needed to
manually select the &ldquo;Nim&rdquo; subject even when I called that function
from a <code>nim-mode</code> buffer. <em>At least for my use cases, I would want to
access only Nim docs if I am looking up devdocs while in a Nim code
buffer.</em></p>
<p>The package has an interesting function called <code>devdocs-setup</code> which
would generate a function specific to each subject.. so for &ldquo;Nim&rdquo;
subject, it would generate a <code>devdocs-lookup-nim</code> function.</p>
<p>But I wanted to avoid calling <code>devdocs-setup</code> too.</p>
<p>So below is what I did:</p>
<p><a id="code-snippet--devdocs-lookup-modified"></a></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">devdocs-lookup</span> <span class="p">(</span><span class="nv">subject</span> <span class="nv">entry</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Visit the documentation for ENTRY from SUBJECT in a browser.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">interactive</span>
</span></span><span class="line hl"><span class="cl">   <span class="p">(</span><span class="nb">cl-letf</span> <span class="p">(((</span><span class="nf">symbol-function</span> <span class="ss">&#39;string-match-case-insensitive</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl">              <span class="p">(</span><span class="nb">lambda</span> <span class="p">(</span><span class="nv">str1</span> <span class="nv">str2</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl">                <span class="p">(</span><span class="nv">string=</span> <span class="p">(</span><span class="nf">downcase</span> <span class="nv">str1</span><span class="p">)</span> <span class="p">(</span><span class="nf">downcase</span> <span class="nv">str2</span><span class="p">)))))</span>
</span></span><span class="line hl"><span class="cl">     <span class="p">(</span><span class="nb">let*</span> <span class="p">((</span><span class="nv">major-mode-str</span> <span class="p">(</span><span class="nv">replace-regexp-in-string</span> <span class="s">&#34;-mode&#34;</span> <span class="s">&#34;&#34;</span> <span class="p">(</span><span class="nf">symbol-name</span> <span class="nv">major-mode</span><span class="p">)))</span>
</span></span><span class="line hl"><span class="cl">            <span class="c1">;; If major mode is `nim-mode&#39;, the (&#34;Nim&#34; &#34;nim&#34;) element</span>
</span></span><span class="line hl"><span class="cl">            <span class="c1">;; will be auto-picked from `devdocs-subjects&#39;.</span>
</span></span><span class="line hl"><span class="cl">            <span class="p">(</span><span class="nv">subject-dwim</span> <span class="p">(</span><span class="nv">cadr</span> <span class="p">(</span><span class="nf">assoc</span> <span class="nv">major-mode-str</span> <span class="nv">devdocs-subjects</span>
</span></span><span class="line hl"><span class="cl">                                       <span class="nf">#&#39;</span><span class="nv">string-match-case-insensitive</span><span class="p">)))</span>
</span></span><span class="line hl"><span class="cl">            <span class="p">(</span><span class="nv">subject</span> <span class="p">(</span><span class="nb">or</span> <span class="nv">subject-dwim</span> <span class="p">(</span><span class="nv">devdocs-read-subject</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">            <span class="p">(</span><span class="nv">entry</span> <span class="p">(</span><span class="nv">devdocs-read-entry</span> <span class="nv">subject</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">       <span class="p">(</span><span class="nf">list</span> <span class="nv">subject</span> <span class="nv">entry</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">path</span> <span class="p">(</span><span class="nf">cdr</span> <span class="p">(</span><span class="nf">assoc</span> <span class="nv">entry</span> <span class="p">(</span><span class="nv">devdocs-entries</span> <span class="nv">subject</span><span class="p">)))))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">when</span> <span class="nv">path</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nv">browse-url</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;%s/%s/%s&#34;</span> <span class="nv">devdocs-base-url</span> <span class="nv">subject</span> <span class="nv">path</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">      <span class="nb">:found</span><span class="p">)))</span>
</span></span></code></pre></div><div class="src-block-caption">
  <span class="src-block-number"><a href="#code-snippet--devdocs-lookup-modified">Code Snippet 5</a>:</span>
  Modification of the original <code>devdocs-lookup</code> &#x2013; Now auto-selects the subject if the <code>major-mode</code> matches.
</div>

<h4 id="auto-filter-using-the-symbol-at-point">Auto-filter using the symbol at point&nbsp;<a class="headline-hash no-text-decoration" href="#auto-filter-using-the-symbol-at-point">#</a></h4>


<p>The second thing that I wanted to work upon was to make Emacs kind of
&ldquo;know&rdquo; what I was trying to search.</p>
<p>Originally, <code>devdocs-read-entry</code> would always show the completion-list
pointing at the first entry. I wanted to make that a bit more
intelligent.. If my point were on the <code>walkDirRec</code> <em>proc</em> identifier
on a line like below,</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nim" data-lang="nim"><span class="line"><span class="cl"><span class="k">for</span> <span class="n">filepath</span> <span class="ow">in</span> <span class="n">walkDirRec</span><span class="p">(</span><span class="n">appPath</span><span class="p">,</span> <span class="n">yieldFilter</span><span class="o">=</span><span class="p">{</span><span class="n">pcFile</span><span class="p">}):</span>
</span></span></code></pre></div><p>I wanted the collection to narrow down to only the entries that
matched &ldquo;walkDirRec&rdquo;.</p>
<p>Below is my modification to do that.</p>
<p><a id="code-snippet--devdocs-read-entry-modified"></a></p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-emacs-lisp" data-lang="emacs-lisp"><span class="line"><span class="cl"><span class="p">(</span><span class="nb">defun</span> <span class="nv">devdocs-read-entry</span> <span class="p">(</span><span class="nv">subject</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">  <span class="s">&#34;Interactively ask the user for an entry in SUBJECT.&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">(</span><span class="nb">let</span> <span class="p">((</span><span class="nv">names</span> <span class="p">(</span><span class="nf">mapcar</span> <span class="nf">#&#39;car</span> <span class="p">(</span><span class="nv">devdocs-entries</span> <span class="nv">subject</span><span class="p">)))</span>
</span></span><span class="line"><span class="cl">        <span class="p">(</span><span class="nv">hist</span> <span class="p">(</span><span class="nf">intern</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;devdocs--hist-%s&#34;</span> <span class="nv">subject</span><span class="p">)))</span>
</span></span><span class="line hl"><span class="cl">        <span class="p">(</span><span class="nv">init</span> <span class="p">(</span><span class="nf">symbol-name</span> <span class="p">(</span><span class="nv">symbol-at-point</span><span class="p">))))</span>
</span></span><span class="line"><span class="cl">    <span class="p">(</span><span class="nb">unless</span> <span class="p">(</span><span class="nf">boundp</span> <span class="nv">hist</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">      <span class="p">(</span><span class="nf">set</span> <span class="nv">hist</span> <span class="no">nil</span><span class="p">))</span>
</span></span><span class="line hl"><span class="cl">    <span class="p">(</span><span class="nf">completing-read</span> <span class="p">(</span><span class="nf">format</span> <span class="s">&#34;Entry (%s): &#34;</span> <span class="nv">subject</span><span class="p">)</span> <span class="nv">names</span> <span class="no">nil</span> <span class="nb">:require-match</span> <span class="nv">init</span> <span class="nv">hist</span><span class="p">)))</span>
</span></span></code></pre></div><div class="src-block-caption">
  <span class="src-block-number"><a href="#code-snippet--devdocs-read-entry-modified">Code Snippet 6</a>:</span>
  Modification of the original <code>devdocs-read-entry</code> &#x2013; Now auto-filters the entries that match the symbol at point.
</div>
<p>Above function just pre-sets the filter.. If the user wants to change
the search string, they can still do that.</p>

<h2 id="using-devdocs-lookup">Using <code>devdocs-lookup</code>&nbsp;<a class="headline-hash no-text-decoration" href="#using-devdocs-lookup">#</a></h2>


<p>Finally, I like the <a href="https://www.emacswiki.org/emacs/key-chord.el"><code>key-chord.el</code></a> package. So using that, I bind the
<code>??</code> key-chord to the modified <code>devdocs-lookup</code> function.</p>
<p>So if I want to look up the docs for <code>walkDirRec</code> on that line in the
above example, I just move the point there, and hit <code>??</code>, and the docs
for that will pop up in my browser..</p>
<ul>
<li>No manual launching of the browser.</li>
<li>No manual typing of the search string.</li>
</ul>

<h2 id="devdocs-lookup-demo">Demo&nbsp;<a class="headline-hash no-text-decoration" href="#devdocs-lookup-demo">#</a></h2>


<p>It won&rsquo;t be fun if I did not end this post without a demo. So here it
is &mdash;</p>
<p><a id="figure--nim-devdocs-gif"></a></p>



<figure>
    <a href="nim-devdocs.gif">
        <img src="https://scripter.co/accessing-devdocs-from-emacs/nim-devdocs-screenshot.png" alt="Figure 1: Click the above image to see the devdocs.io access from Emacs in action (GIF)"/> </a><figcaption>
                <p>
                    <span class="figure-number">Figure 1: </span>Click the above image to see the devdocs.io access from Emacs in action (GIF)
                    
                        
                        </p>
                
            </figcaption></figure>


<h2 id="devdocs-lookup-code">Code&nbsp;<a class="headline-hash no-text-decoration" href="#devdocs-lookup-code">#</a></h2>


<p>You can find the modified <code>devdocs-lookup</code> code <a href="https://github.com/kaushalmodi/devdocs-lookup">here</a>.</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>All of the code snippets from Christopher Wellon&rsquo;s
<code>devdocs-lookup</code> that now follow in this post are from <a href="https://github.com/skeeto/devdocs-lookup/tree/021c3c95030b4ee0d83a6961804c7a347faa72de">this commit</a>.&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
<li id="fn:2">
<p>If you visit that file in Firefox, it will show up in a
wonderful formatted form with collapsible drawers, search, etc.&#160;<a href="#fnref:2" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content><category scheme="https://scripter.co/categories/emacs" term="emacs" label="emacs"/><category scheme="https://scripter.co/tags/devdocs" term="devdocs" label="devdocs"/><category scheme="https://scripter.co/tags/documentation" term="documentation" label="documentation"/><category scheme="https://scripter.co/tags/nim" term="nim" label="nim"/><category scheme="https://scripter.co/tags/search" term="search" label="search"/><category scheme="https://scripter.co/tags/package" term="package" label="package"/></entry></feed>