<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>hi, it&#39;s mike</title>
    <link>https://mike.puddingtime.org/tags/lbdb/</link>
    <description>Recent content on hi, it&#39;s mike</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <managingEditor>mike@puddingtime.org (mike)</managingEditor>
    <webMaster>mike@puddingtime.org (mike)</webMaster>
    <copyright>© 2026, mike</copyright>
    <lastBuildDate>Sun, 16 Apr 2023 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://mike.puddingtime.org/tags/lbdb/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>An org-contacts source for lbdb</title>
      <link>https://mike.puddingtime.org/posts/2023-04-16-an-org-contacts-source-for-lbdb/</link>
      <pubDate>Sun, 16 Apr 2023 00:00:00 +0000</pubDate><author>mike@puddingtime.org (mike)</author>
      <guid>https://mike.puddingtime.org/posts/2023-04-16-an-org-contacts-source-for-lbdb/</guid>
      <description>I modified a Perl lbdb backend by ‪@publicvoit@graz.social ‬to use my org-contacts with mutt</description>
      <content:encoded><![CDATA[<p>This is a ruby-based back-end for <a href="https://www.spinnaker.de/lbdb/">The Little Brother&rsquo;s Database (lbdb)</a> that looks at a hard-coded <code>org-contacts</code> file. The idea comes from <a href="https://lists.gnu.org/archive/html/emacs-orgmode/2011-10/msg01059.html">a 2011 Perl implementation by Karl Voit</a>. Because I am not a Perl person, when it didn&rsquo;t work out of the box I converted it to Ruby.</p>
<p>And because I&rsquo;ve chosen to treat org-contacts as <code>TODO</code> items for purposes of remembering who to <code>PING</code>, <code>FOLLOWUP</code>, <code>SKED</code>, etc. it has to take the extra step of stripping those keywords from the returned name. Otherwise, my mails to Joe Grudd would be addressed to <code>FOLLOWUP Joe Grudd</code>.</p>
<p>That&rsquo;s a small bit of inelegance in my plaintext CRM setup:  As I&rsquo;ve figured out more about how <code>org-super-agenda</code> works, I&rsquo;ve had glimpses of how the plaintext CRM metadata could just be content in the <code>:PROPERTIES:</code> drawer, and hence invisible for purposes of tools like this, but a few other pieces of passive automation would have to become some sort of org-mode hook and I&rsquo;d lose the utility of tools like Beorg, which can&rsquo;t provide the automation of native Emacs.</p>
<p>For now, it&rsquo;s one of those &ldquo;this design isn&rsquo;t the cleanest, but it&rsquo;s simple and only creates a few easily solved problems&rdquo; things.</p>
<p>Here&rsquo;s the script itself. I put it in <code>~/bin</code> as <code>orgcontact.rb</code>:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-ruby" data-lang="ruby"><span class="line"><span class="cl"><span class="ch">#!/usr/bin/env ruby</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Get the query string</span>
</span></span><span class="line"><span class="cl"><span class="n">query</span> <span class="o">=</span> <span class="no">ARGV</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Set the path to your Org-contacts file</span>
</span></span><span class="line"><span class="cl"><span class="n">orgmodefile</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">#{</span><span class="no">ENV</span><span class="o">[</span><span class="s1">&#39;HOME&#39;</span><span class="o">]</span><span class="si">}</span><span class="s2">/org/contacts.org&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Read in the whole contact file</span>
</span></span><span class="line"><span class="cl"><span class="n">raw_contacts</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">orgmodefile</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">** &#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Iterate through each contact</span>
</span></span><span class="line"><span class="cl"><span class="n">raw_contacts</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">contact</span><span class="o">|</span>
</span></span><span class="line"><span class="cl">  <span class="k">if</span> <span class="n">contact</span><span class="o">.</span><span class="n">match?</span><span class="p">(</span><span class="sr">/</span><span class="si">#{</span><span class="n">query</span><span class="si">}</span><span class="sr">/i</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Extract the name and email from the contact</span>
</span></span><span class="line"><span class="cl">    <span class="nb">name</span> <span class="o">=</span> <span class="n">contact</span><span class="o">[</span><span class="sr">/^[^\n]*/</span><span class="o">].</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/(PING|INVITE|WRITE|PINGED|FOLLOWUP|SKED|NOTES|SCHEDULED|TIMEOUT|OK)\s+/i</span><span class="p">,</span> <span class="s2">&#34;&#34;</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span>
</span></span><span class="line"><span class="cl">    <span class="n">email</span> <span class="o">=</span> <span class="n">contact</span><span class="o">[</span><span class="sr">/:EMAIL:\s+(.*)$/</span><span class="p">,</span> <span class="mi">1</span><span class="o">]</span>
</span></span><span class="line"><span class="cl">    <span class="c1"># Remove tags from the name</span>
</span></span><span class="line"><span class="cl">    <span class="nb">name</span><span class="o">.</span><span class="n">gsub!</span><span class="p">(</span><span class="sr">/:\S+:/</span><span class="p">,</span> <span class="s1">&#39;&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">    <span class="nb">puts</span> <span class="s2">&#34;</span><span class="si">#{</span><span class="n">email</span><span class="si">}</span><span class="se">\t</span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="se">\t</span><span class="s2">(org-contacts)&#34;</span> <span class="k">if</span> <span class="nb">name</span> <span class="o">&amp;&amp;</span> <span class="n">email</span>
</span></span><span class="line"><span class="cl">  <span class="k">end</span>
</span></span><span class="line"><span class="cl"><span class="k">end</span></span></span></code></pre></div>
<p>Adding <code>m_org_contacts</code> to the <code>METHODS</code> setting then including a little wrapper in <code>~/.lbdbrc</code> doesn&rsquo;t follow the canonical advice on how to configure an lbdb backend, but it works, and it&rsquo;s one less file to put somewhere:</p>






<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">METHODS=&#34;m_osx_addressbook m_org_contacts&#34;
</span></span><span class="line"><span class="cl">MODULES_PATH=&#34;$MODULES_PATH $HOME/bin/lbdb&#34;
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">m_org_contacts_query() {
</span></span><span class="line"><span class="cl">   ~/bin/orgcontact.rb &#34;$1&#34;
</span></span><span class="line"><span class="cl">}</span></span></code></pre></div>
<p>So, the outcome is just:</p>
<ol>
<li>
<p>Start a new message in mutt and start typing the name/address/etc.</p>
</li>
<li>
<p>lbdb provides a list of matches from a few sources I&rsquo;ve set up: org-contacts and macOS address book</p>
</li>
<li>
<p><code>ENTER</code> to select a candidate</p>
<p>b</p>
</li>
</ol>
]]></content:encoded>
    </item>
  </channel>
</rss>
