<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Develop With Passion®]]></title>
  <link href="http://blog.developwithpassion.com/atom.xml" rel="self"/>
  <link href="http://blog.developwithpassion.com/"/>
  <updated>2013-05-02T14:54:09-06:00</updated>
  <id>http://blog.developwithpassion.com/</id>
  <author>
    <name><![CDATA[Develop With Passion®]]></name>
    
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Getting Up And Running With A Sane Mutt Setup]]></title>
    <link href="http://blog.developwithpassion.com/2013/05/02/getting-up-and-running-with-a-sane-mutt-setup/"/>
    <updated>2013-05-02T09:58:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2013/05/02/getting-up-and-running-with-a-sane-mutt-setup</id>
    <content type="html"><![CDATA[<p>Well, for the last 2 months I have been using <a href="http://www.mutt.org/">Mutt</a> as my primary email client, and I have not missed gmail at all!!</p>

<p>I spend the majority of my day inside a shell based environment, and a large majority of my workflow/tooling has been heavily modded to allow me to do the majority of my computer related activities from a shell.</p>

<ul>
<li>I edit all my code in vim</li>
<li>I manage keychain entries using the command line clients</li>
<li>I have a easy to customize automation/expansion library that allows me to add new shell automation tasks easily</li>
<li>For the rare times that I use twitter, I use a vim plugin for that!</li>
<li>I compose blog entries in vim</li>
</ul>


<p>You get the point!</p>

<p>I have occassionally messed around with using <a href="">links</a> as a browser client. In reality, between chrome+vimium or firefox+vimperator, I have my mouseless browsing covered. The only scenario this setup does not work well for me is when I am ssh&#8217;d into a machine and want to browse the web (hence the use of links in those scenarios).</p>

<h2>Focused, specific tools that do one job and do it well</h2>

<p>This post is mostly for my own journalling purposes, but I am sharing it in the event that it proves useful to others. If you are running on osx, I am going to strongly recommend that you install the <a href="http://mxcl.github.io/homebrew/">homebrew</a> package manager, as that is what I use, to install other programs.</p>

<p>This post will outline the way that I setup the following tools:</p>

<ul>
<li><a href="">mutt - Shell based email client</a></li>
<li><a href="">offlineimap - Offline imap mail management</a></li>
<li><a href="">urlview - View urls in files</a></li>
<li><a href="">msmtp - Smtp client</a></li>
<li><a href="">gnupg - Encyrption utilities</a></li>
</ul>


<h2>Getting Started</h2>

<p>As noted above, you will more than likely want to install <a href="http://docs.offlineimap.org/en/latest/FAQ.html#id8">homebrew</a> to follow along with these instructions the best. I love homebrew as it is a ruby based package management system for non gem based packages (think nodejs, sqlite &#8230;)</p>

<h2>Installing and configuring offlineimap</h2>

<p>After a brief 30 minute session messing around with mutt as a simple gmail client I was running into a lot of annoying &#8220;freezes&#8221;. I came to the conclusion that using mutt as a replacement for the Gmail web interface would not really bring me a lot of the benefits that I wanted from a shell based email interface. I decided that it would be handy to be able to manage email offline, which would allow me to not have to connect to gmail unless I
actually needed to send emails or synchronize local changes. To that end I decided to go with <a href="http://offlineimap.org/">offlineimap</a> to download a complete copy of my gmail imap folders and be able to deal with mail completely offline if need be.</p>

<p>As is the case with the rest of the tools in this guide, the install process is a snap, the configuration process is a little involved. I installed the current version of offlineimap.  To install offline imap just type the following in a shell:</p>

<figure class='code'><figcaption><span>Install Homebrew - install.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>
</span><span class='line'>brew install offlineimap
</span><span class='line'>brew install sqlite
</span></code></pre></td></tr></table></div></figure>


<p>I installed sqlite to use it as the storage for offlineimap mail status.</p>

<p>Ok, that was painless now lets configure it:</p>

<figure class='code'><figcaption><span>Copy Initial Configuration File - copy_config.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>
</span><span class='line'>cp <span class="k">$(</span>brew --prefix<span class="k">)</span>/Cellar/offlineimap/HEAD/offlineimap.conf ~/.offlineimaprc
</span></code></pre></td></tr></table></div></figure>


<p>This just copies a stock sample configuration file into one of the standard places that offlineimap looks for configuration. To read more about offlineimap configuration go <a href="http://docs.offlineimap.org/en/latest/MANUAL.html#configuration">here</a>. I spent quite a bit of time reading through the docs and messing around with a bunch of the settings, along with messing up my install a couple of times!! That is how I learn the best though!! The documentation that comes with the sample configuration file is pretty informative, so you should be able to tweak a lot of things. As far as configuration goes I leveraged the sample configuration outlined by <a href="http://stevelosh.com/blog/2012/10/the-homely-mutt/#configuring-offlineimap">Steve Losh</a>, who also went through the joys of configuring this setup a while ago. I wanted to understand how all these pieces worked, so I just leveraged his guide to rip off his configuration. His guide is also a great walkthrough of how to get this setup going. I am of the mindset that I like to struggle on my own for a bit as I try to figure things out. Instead of using his and other awesome guides, I set aside a half day and did this myself!! In the docs it mentions that the offlineimaprc file can also include a regular python file that can have supplementary code you want to leverage!! Pretty awesome concept. Steve uses this in a clever way to get around the need to have plain text passwords in the config file. Read his post for the details, but it basically makes use of the security utility (usr/bin/security on most unix based systems), to access the password in a keychain item.</p>

<p>Ok, so I configured things appropriately and was ready to kick off offlineimap to download the mail locally onto my computer (only about 1.5GB, but seeing as how we live out in the boonies, this would take a while). I fired up offlineimap and was immediately hit with an error about an incorrect fingerprint for the gmail stmp server. I figured this had something to do with a gmail cert change. This was rectified by following the instructions <a href="https://wiki.archlinux.org/index.php/OfflineIMAP#SSL_fingerprint_does_not_match">here</a> which resulted in my adding the following config item in my JPBoodhoo-Remote Repository section:</p>

<figure class='code'><figcaption><span>Adding gmail cert fingerprint - cert_fingerprint.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>
</span><span class='line'><span class="nv">cert_fingerprint</span> <span class="o">=</span> 6d1b5b5ee0180ab493b71d3b94534b5ab937d042
</span></code></pre></td></tr></table></div></figure>


<p>With that change in place (keep in mind, the fingerprint can change at a later time, which would require this line to be updated), things looked good to go, I reran offlineimap and went about with other work while our blazingly fast connection proceeded to choke on the download for the next couple of hours.</p>

<p>Here is the majority of the pertinent stuff from my current configuration:</p>

<figure class='code'><figcaption><span>offlineimap configuration - configuration.ini </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
</pre></td><td class='code'><pre><code class='ini'><span class='line'>
</span><span class='line'><span class="k">[general]</span>
</span><span class='line'><span class="na">ui</span> <span class="o">=</span> <span class="s">TTYUI</span>
</span><span class='line'><span class="na">accounts</span> <span class="o">=</span> <span class="s">jp_developwithpassion_gmail, jboodhoo------gmail</span>
</span><span class='line'><span class="na">pythonfile</span> <span class="o">=</span> <span class="s">~/repositories/developwithpassion/devtools/shared/dotfiles/offlineimap/offlineimap.py</span>
</span><span class='line'><span class="na">fsync</span> <span class="o">=</span> <span class="s">False</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="k">[Account jp_developwithpassion_gmail]</span>
</span><span class='line'><span class="na">localrepository</span> <span class="o">=</span> <span class="s">jp_developwithpassion_gmail_local</span>
</span><span class='line'><span class="na">remoterepository</span> <span class="o">=</span> <span class="s">jp_developwithpassion_gmail_remote</span>
</span><span class='line'><span class="na">status_backend</span> <span class="o">=</span> <span class="s">sqlite</span>
</span><span class='line'><span class="na">postsynchook</span> <span class="o">=</span> <span class="s">notmuch new</span>
</span><span class='line'>
</span><span class='line'><span class="k">[Account jboodhoo----gmail]</span>
</span><span class='line'><span class="na">localrepository</span> <span class="o">=</span> <span class="s">jboodhoo----gmail_local</span>
</span><span class='line'><span class="na">remoterepository</span> <span class="o">=</span> <span class="s">jboodhoo----gmail_remote</span>
</span><span class='line'><span class="na">status_backend</span> <span class="o">=</span> <span class="s">sqlite</span>
</span><span class='line'><span class="na">postsynchook</span> <span class="o">=</span> <span class="s">notmuch new</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="c">#developwithpassion</span>
</span><span class='line'><span class="k">[Repository jp_developwithpassion_gmail_local]</span>
</span><span class='line'><span class="na">type</span> <span class="o">=</span> <span class="s">Maildir</span>
</span><span class='line'><span class="na">localfolders</span> <span class="o">=</span> <span class="s">~/Dropbox/imap_mail/jp_developwithpassion</span>
</span><span class='line'><span class="na">nametrans</span> <span class="o">=</span> <span class="s">get_remote_name</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="k">[Repository jp_developwithpassion_gmail_remote]</span>
</span><span class='line'><span class="na">maxconnections</span> <span class="o">=</span> <span class="s">1</span>
</span><span class='line'><span class="na">type</span> <span class="o">=</span> <span class="s">Gmail</span>
</span><span class='line'><span class="na">cert_fingerprint</span> <span class="o">=</span> <span class="s">6d1b5b5ee0180ab493b71d3b94534b5ab937d042 </span>
</span><span class='line'><span class="na">remoteuser</span> <span class="o">=</span> <span class="s">jp@developwithpassion.com</span>
</span><span class='line'><span class="na">remotepasseval</span> <span class="o">=</span> <span class="s">get_password(&quot;jp@developwithpassion.com&quot;)</span>
</span><span class='line'><span class="na">realdelete</span> <span class="o">=</span> <span class="s">no</span>
</span><span class='line'><span class="na">nametrans</span> <span class="o">=</span> <span class="s">get_local_name</span>
</span><span class='line'><span class="na">folderfilter</span> <span class="o">=</span> <span class="s">is_included</span>
</span><span class='line'>
</span><span class='line'><span class="c">#***</span>
</span><span class='line'><span class="k">[Repository jboodhoo-----gmail_local]</span>
</span><span class='line'><span class="na">type</span> <span class="o">=</span> <span class="s">Maildir</span>
</span><span class='line'><span class="na">localfolders</span> <span class="o">=</span> <span class="s">~/Dropbox/imap_mail/jboodhoo---</span>
</span><span class='line'><span class="na">nametrans</span> <span class="o">=</span> <span class="s">get_remote_name</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="k">[Repository jboodhoo----gmail_remote]</span>
</span><span class='line'><span class="na">maxconnections</span> <span class="o">=</span> <span class="s">1</span>
</span><span class='line'><span class="na">type</span> <span class="o">=</span> <span class="s">Gmail</span>
</span><span class='line'><span class="na">cert_fingerprint</span> <span class="o">=</span> <span class="s">6d1b5b5ee0180ab493b71d3b94534b5ab937d042 </span>
</span><span class='line'><span class="na">remoteuser</span> <span class="o">=</span> <span class="s">jboodhoo@----</span>
</span><span class='line'><span class="na">remotepasseval</span> <span class="o">=</span> <span class="s">get_password(&quot;jboodhoo@----&quot;)</span>
</span><span class='line'><span class="na">realdelete</span> <span class="o">=</span> <span class="s">no</span>
</span><span class='line'><span class="na">nametrans</span> <span class="o">=</span> <span class="s">get_local_name</span>
</span><span class='line'><span class="na">folderfilter</span> <span class="o">=</span> <span class="s">is_included</span>
</span></code></pre></td></tr></table></div></figure>


<p>You can check out Steves post for a very thorough explanation of the configuration that matches. I took advantage of the python file to DRY up my configuration for the nametrans setting. When you are working with one of the remote repositories (jp_developwithpassion_gmail_remote) in one of the examples above; the nametrans setting determines how to map the remote imap folder names to names on your local machine. In the examples on the offlineimap site, they would set up reverse entries in
the nametrans for the local and remote options. That would look something like this (lifted from some standard example online):</p>

<figure class='code'><figcaption><span>nametrans configuration - nametrans.ini </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
</pre></td><td class='code'><pre><code class='ini'><span class='line'><span class="k">[Repository blah-Local]</span>
</span><span class='line'><span class="na">type</span> <span class="o">=</span> <span class="s">Maildir</span>
</span><span class='line'><span class="na">localfolders</span> <span class="o">=</span> <span class="s">~/.mail/blah.com</span>
</span><span class='line'><span class="na">nametrans</span> <span class="o">=</span> <span class="s">lambda folder: {&#39;drafts&#39;:  &#39;[Gmail]/Drafts&#39;,</span>
</span><span class='line'><span class="s">                            &#39;sent&#39;:    &#39;[Gmail]/Sent Mail&#39;,</span>
</span><span class='line'><span class="s">                            &#39;flagged&#39;: &#39;[Gmail]/Starred&#39;,</span>
</span><span class='line'><span class="s">                            &#39;trash&#39;:   &#39;[Gmail]/Trash&#39;,</span>
</span><span class='line'><span class="s">                            &#39;archive&#39;: &#39;[Gmail]/All Mail&#39;,</span>
</span><span class='line'><span class="s">                            }.get(folder, folder)</span>
</span><span class='line'>
</span><span class='line'><span class="k">[Repository blah-Remote]</span>
</span><span class='line'><span class="na">maxconnections</span> <span class="o">=</span> <span class="s">1</span>
</span><span class='line'><span class="na">type</span> <span class="o">=</span> <span class="s">Gmail</span>
</span><span class='line'><span class="na">remoteuser</span> <span class="o">=</span> <span class="s">blah@blah.com</span>
</span><span class='line'><span class="na">remotepasseval</span> <span class="o">=</span> <span class="s">&quot;password&quot;</span>
</span><span class='line'><span class="na">realdelete</span> <span class="o">=</span> <span class="s">no</span>
</span><span class='line'><span class="na">nametrans</span> <span class="o">=</span> <span class="s">lambda folder: {&#39;[Gmail]/Drafts&#39;:    &#39;drafts&#39;,</span>
</span><span class='line'><span class="s">                            &#39;[Gmail]/Sent Mail&#39;: &#39;sent&#39;,</span>
</span><span class='line'><span class="s">                            &#39;[Gmail]/Starred&#39;:   &#39;flagged&#39;,</span>
</span><span class='line'><span class="s">                            &#39;[Gmail]/Trash&#39;:     &#39;trash&#39;,</span>
</span><span class='line'><span class="s">                            &#39;[Gmail]/All Mail&#39;:  &#39;archive&#39;,</span>
</span><span class='line'><span class="s">                            }.get(folder, folder)</span>
</span></code></pre></td></tr></table></div></figure>


<p>Of course, as you can see above, it seems a little redundant. In my config I dry it up as follows:</p>

<figure class='code'><figcaption><span>Drying up the name translation - nametrans_dry.ini </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
</pre></td><td class='code'><pre><code class='ini'><span class='line'><span class="k">[Repository jp_developwithpassion_gmail_local]</span>
</span><span class='line'><span class="na">type</span> <span class="o">=</span> <span class="s">Maildir</span>
</span><span class='line'><span class="na">localfolders</span> <span class="o">=</span> <span class="s">~/Dropbox/imap_mail/jp_developwithpassion</span>
</span><span class='line'><span class="na">nametrans</span> <span class="o">=</span> <span class="s">get_remote_name</span>
</span><span class='line'>
</span><span class='line'><span class="k">[Repository jp_developwithpassion_gmail_remote]</span>
</span><span class='line'><span class="na">maxconnections</span> <span class="o">=</span> <span class="s">1</span>
</span><span class='line'><span class="na">type</span> <span class="o">=</span> <span class="s">Gmail</span>
</span><span class='line'><span class="na">cert_fingerprint</span> <span class="o">=</span> <span class="s">6d1b5b5ee0180ab493b71d3b94534b5ab937d042 </span>
</span><span class='line'><span class="na">remoteuser</span> <span class="o">=</span> <span class="s">jp@developwithpassion.com</span>
</span><span class='line'><span class="na">remotepasseval</span> <span class="o">=</span> <span class="s">get_password(&quot;jp@developwithpassion.com&quot;)</span>
</span><span class='line'><span class="na">realdelete</span> <span class="o">=</span> <span class="s">no</span>
</span><span class='line'><span class="na">nametrans</span> <span class="o">=</span> <span class="s">get_local_name</span>
</span><span class='line'><span class="na">folderfilter</span> <span class="o">=</span> <span class="s">is_included</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is done by leveraging the following code that exists in the python file that I include at the top of my configuration:</p>

<figure class='code'><figcaption><span>OfflineImap Python Configuration - offline.py </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
<span class='line-number'>70</span>
<span class='line-number'>71</span>
<span class='line-number'>72</span>
<span class='line-number'>73</span>
<span class='line-number'>74</span>
<span class='line-number'>75</span>
<span class='line-number'>76</span>
<span class='line-number'>77</span>
<span class='line-number'>78</span>
<span class='line-number'>79</span>
<span class='line-number'>80</span>
<span class='line-number'>81</span>
<span class='line-number'>82</span>
<span class='line-number'>83</span>
<span class='line-number'>84</span>
<span class='line-number'>85</span>
<span class='line-number'>86</span>
<span class='line-number'>87</span>
<span class='line-number'>88</span>
<span class='line-number'>89</span>
<span class='line-number'>90</span>
<span class='line-number'>91</span>
<span class='line-number'>92</span>
<span class='line-number'>93</span>
<span class='line-number'>94</span>
<span class='line-number'>95</span>
<span class='line-number'>96</span>
<span class='line-number'>97</span>
<span class='line-number'>98</span>
<span class='line-number'>99</span>
<span class='line-number'>100</span>
<span class='line-number'>101</span>
<span class='line-number'>102</span>
</pre></td><td class='code'><pre><code class='py'><span class='line'><span class="c">#!/usr/bin/python</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">subprocess</span>
</span><span class='line'><span class="kn">import</span> <span class="nn">re</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">NameMapping</span><span class="p">:</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">local_name</span><span class="p">,</span> <span class="n">remote_name</span><span class="p">):</span>
</span><span class='line'>    <span class="bp">self</span><span class="o">.</span><span class="n">local_name</span> <span class="o">=</span> <span class="n">local_name</span>
</span><span class='line'>    <span class="bp">self</span><span class="o">.</span><span class="n">remote_name</span> <span class="o">=</span> <span class="n">remote_name</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">LocalName</span><span class="p">:</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">folder</span><span class="p">):</span>
</span><span class='line'>    <span class="bp">self</span><span class="o">.</span><span class="n">folder</span> <span class="o">=</span> <span class="n">folder</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">matches</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mapping</span><span class="p">):</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">mapping</span><span class="o">.</span><span class="n">remote_name</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">folder</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">mapped_folder_name</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mapping</span><span class="p">):</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">mapping</span><span class="o">.</span><span class="n">local_name</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">RemoteName</span><span class="p">:</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">folder</span><span class="p">):</span>
</span><span class='line'>    <span class="bp">self</span><span class="o">.</span><span class="n">folder</span> <span class="o">=</span> <span class="n">folder</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">matches</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mapping</span><span class="p">):</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">mapping</span><span class="o">.</span><span class="n">local_name</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">folder</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">mapped_folder_name</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">mapping</span><span class="p">):</span>
</span><span class='line'>    <span class="k">return</span> <span class="n">mapping</span><span class="o">.</span><span class="n">remote_name</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_password</span><span class="p">(</span><span class="n">account</span><span class="p">):</span>
</span><span class='line'>  <span class="n">program</span> <span class="o">=</span><span class="s">&#39;/Users/jp/repositories/developwithpassion/devtools/automation/keychain/get_keychain_password&#39;</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">command</span> <span class="o">=</span> <span class="s">&quot;{0} --account:{1}&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">program</span><span class="p">,</span> <span class="n">account</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">output</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">check_output</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="n">output</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">is_included</span><span class="p">(</span><span class="n">folder</span><span class="p">):</span>
</span><span class='line'>  <span class="n">result</span> <span class="o">=</span> <span class="bp">True</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="n">pattern</span> <span class="ow">in</span> <span class="n">exclusion_patterns</span><span class="p">:</span>
</span><span class='line'>    <span class="n">result</span> <span class="o">=</span> <span class="n">result</span> <span class="ow">and</span> <span class="p">(</span><span class="n">re</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="n">pattern</span><span class="p">,</span> <span class="n">folder</span><span class="p">)</span> <span class="o">==</span> <span class="bp">None</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="n">result</span>
</span><span class='line'>
</span><span class='line'><span class="n">exclusion_patterns</span> <span class="o">=</span> <span class="p">[</span>
</span><span class='line'>  <span class="s">&quot;efax&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;earth_class_mail&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;eventbrite&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;gotomeeting&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;moshi_monsters&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;peepcode&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;raini_fowl&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;stuart_know&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;training.*2008&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;training.*2009&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;training.*2010&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;training.*2011&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;training.*2012&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;training.*nbdn&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;training.*nothin_but_bdd&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;unblock_us&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;web_hosting&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;webinars&quot;</span><span class="p">,</span>
</span><span class='line'>  <span class="s">&quot;Gmail.*Important&quot;</span>
</span><span class='line'><span class="p">]</span>
</span><span class='line'>
</span><span class='line'><span class="n">name_mappings</span> <span class="o">=</span> <span class="p">[</span>
</span><span class='line'>  <span class="n">NameMapping</span><span class="p">(</span><span class="s">&#39;sent&#39;</span><span class="p">,</span> <span class="s">&#39;[Gmail]/Sent Mail&#39;</span><span class="p">),</span>
</span><span class='line'>  <span class="n">NameMapping</span><span class="p">(</span><span class="s">&#39;spam&#39;</span><span class="p">,</span> <span class="s">&#39;[Gmail]/Spam&#39;</span><span class="p">),</span>
</span><span class='line'>  <span class="n">NameMapping</span><span class="p">(</span><span class="s">&#39;flagged&#39;</span><span class="p">,</span> <span class="s">&#39;[Gmail]/Starred&#39;</span><span class="p">),</span>
</span><span class='line'>  <span class="n">NameMapping</span><span class="p">(</span><span class="s">&#39;trash&#39;</span><span class="p">,</span>   <span class="s">&#39;[Gmail]/Trash&#39;</span><span class="p">),</span>
</span><span class='line'>  <span class="n">NameMapping</span><span class="p">(</span><span class="s">&#39;archive&#39;</span><span class="p">,</span> <span class="s">&#39;[Gmail]/All Mail&#39;</span><span class="p">),</span>
</span><span class='line'>  <span class="n">NameMapping</span><span class="p">(</span><span class="s">&#39;drafts&#39;</span><span class="p">,</span> <span class="s">&#39;[Gmail]/Drafts&#39;</span><span class="p">)</span>
</span><span class='line'><span class="p">]</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">find_name_mapping</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
</span><span class='line'>  <span class="n">default_mapping</span> <span class="o">=</span> <span class="n">NameMapping</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">folder</span><span class="p">,</span> <span class="n">name</span><span class="o">.</span><span class="n">folder</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">for</span> <span class="n">mapping</span> <span class="ow">in</span> <span class="n">name_mappings</span><span class="p">:</span>
</span><span class='line'>    <span class="k">if</span> <span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">matches</span><span class="p">(</span><span class="n">mapping</span><span class="p">)):</span>
</span><span class='line'>      <span class="k">return</span> <span class="n">mapping</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">return</span> <span class="n">default_mapping</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_name_mapping</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
</span><span class='line'>  <span class="n">mapping</span> <span class="o">=</span> <span class="n">find_name_mapping</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">name</span><span class="o">.</span><span class="n">mapped_folder_name</span><span class="p">(</span><span class="n">mapping</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_remote_name</span><span class="p">(</span><span class="n">local_folder_name</span><span class="p">):</span>
</span><span class='line'>  <span class="n">name</span> <span class="o">=</span> <span class="n">RemoteName</span><span class="p">(</span><span class="n">local_folder_name</span><span class="p">)</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">get_name_mapping</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_local_name</span><span class="p">(</span><span class="n">remote_folder_name</span><span class="p">):</span>
</span><span class='line'>  <span class="n">name</span> <span class="o">=</span> <span class="n">LocalName</span><span class="p">(</span><span class="n">remote_folder_name</span><span class="p">)</span>
</span><span class='line'>  <span class="k">return</span> <span class="n">get_name_mapping</span><span class="p">(</span><span class="n">name</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<p>The name mappings array is the single place where the mappings are defined. That way I don&#8217;t have to worry about typos between sections. The config also shows how I am doing exclusions as well as shelling out to a custom ruby script to get passwords.</p>

<p>On my second imap sync I got an UID validity error on one of the folders I was trying to sync. This was resolved using the following <a href="http://docs.offlineimap.org/en/latest/FAQ.html#id8">doc</a>.</p>

<p>As you can see from the above config, I have 2 different email accounts that are currently setup. The second account is starred out due to privacy reasons.</p>

<p>One of the cool things about the offlineimap configuration is that you can specify a python file that will get mixed into the current config file and you can leverage code in the python file to help with configuration.  I am using this feature for both retrieving account passwords and for remote &amp; local name translation.</p>

<h2>Installing Mutt</h2>

<p>Next up it was time to get going with mutt. Mutt at its core is a text-based mail client. For the purpose of my setup, I am going to be using it to primarily read and compose messages. It has out of the box support to be able to interface with gmail, and its own smtp utility, but I configured it to use msmtp for smpt. To that end, most of the configuration for mutt will be setting it up to basically be able to work with the local copy of messages
that gets pulled down by offlineimap.</p>

<p>Let&#8217;s install it:</p>

<figure class='code'><figcaption><span>Install Mutt - install_mutt.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>
</span><span class='line'>brew install mutt
</span></code></pre></td></tr></table></div></figure>


<h2>Configuring gpg</h2>

<p>As I am currently working with a client that requires encrypted messages for all internal communications, it was necessary for me to setup and configure mutt with encryption. I am using <a href="https://gpgtools.org/">GPGTools for OSX</a>. After installing and setting up my necessary keys, here is the config that I needed to place in the file ~/.mutt/gpg.rc (your file location may vary), this is only a slight modification of the stock gpg configuration.</p>

<figure class='code'><figcaption><span>GPG Configuration - gpg.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>
</span><span class='line'><span class="c"># -*-muttrc-*-</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># Command formats for gpg.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># This version uses gpg-2comp from</span>
</span><span class='line'><span class="c"># http://70t.de/download/gpg-2comp.tar.gz</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># $Id$</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># %p The empty string when no passphrase is needed,</span>
</span><span class='line'><span class="c"># the string &quot;PGPPASSFD=0&quot; if one is needed.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># This is mostly used in conditional % sequences.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># %f Most PGP commands operate on a single file or a file</span>
</span><span class='line'><span class="c"># containing a message. %f expands to this file&#39;s name.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># %s When verifying signatures, there is another temporary file</span>
</span><span class='line'><span class="c"># containing the detached signature. %s expands to this</span>
</span><span class='line'><span class="c"># file&#39;s name.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># %a In &quot;signing&quot; contexts, this expands to the value of the</span>
</span><span class='line'><span class="c"># configuration variable $pgp_sign_as. You probably need to</span>
</span><span class='line'><span class="c"># use this within a conditional % sequence.</span>
</span><span class='line'><span class="c">#</span>
</span><span class='line'><span class="c"># %r In many contexts, mutt passes key IDs to pgp. %r expands to</span>
</span><span class='line'><span class="c"># a list of key IDs.</span>
</span><span class='line'>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_decode_command</span><span class="o">=</span><span class="s2">&quot;gpg --status-fd=2 %?p?--passphrase-fd 0? --no-verbose --quiet --batch --output - %f&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_verify_command</span><span class="o">=</span><span class="s2">&quot;gpg --status-fd=2 --no-verbose --quiet --batch --output - --verify %s %f&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_decrypt_command</span><span class="o">=</span><span class="s2">&quot;gpg --status-fd=2 %?p?--passphrase-fd 0? --no-verbose --quiet --batch --output - %f&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_sign_command</span><span class="o">=</span><span class="s2">&quot;gpg --no-verbose --batch --quiet --output - %?p?--passphrase-fd 0? --armor --detach-sign --textmode %?a?-u %a? %f&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_clearsign_command</span><span class="o">=</span><span class="s2">&quot;gpg --no-verbose --batch --quiet --output - %?p?--passphrase-fd 0? --armor --textmode --clearsign %?a?-u %a? %f&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_encrypt_only_command</span><span class="o">=</span><span class="s2">&quot;pgpewrap gpg --batch --quiet --no-verbose --output - --encrypt --textmode --armor --always-trust -- -r %r -- %f&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_encrypt_sign_command</span><span class="o">=</span><span class="s2">&quot;pgpewrap gpg %?p?--passphrase-fd 0? --batch --quiet --no-verbose --textmode --output - --encrypt --sign %?a?-u %a? --armor --always-trust -- -r %r -- %f&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_import_command</span><span class="o">=</span><span class="s2">&quot;gpg --no-verbose --import %f&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_export_command</span><span class="o">=</span><span class="s2">&quot;gpg --no-verbose --export --armor %r&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_verify_key_command</span><span class="o">=</span><span class="s2">&quot;gpg --verbose --batch --fingerprint --check-sigs %r&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_list_pubring_command</span><span class="o">=</span><span class="s2">&quot;gpg --no-verbose --batch --quiet --with-colons --list-keys %r&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_list_secring_command</span><span class="o">=</span><span class="s2">&quot;gpg --no-verbose --batch --quiet --with-colons --list-secret-keys %r&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># fetch keys</span>
</span><span class='line'><span class="c"># set pgp_getkeys_command=&quot;pkspxycwrap %r&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># pattern for good signature - may need to be adapted to locale!</span>
</span><span class='line'>
</span><span class='line'><span class="c"># set pgp_good_sign=&quot;^gpgv?: Good signature from &quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># OK, here&#39;s a version which uses gnupg&#39;s message catalog:</span>
</span><span class='line'><span class="c"># set pgp_good_sign=&quot;`gettext -d gnupg -s &#39;Good signature from &quot;&#39; | tr -d &#39;&quot;&#39;`&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># This version uses --status-fd messages</span>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_good_sign</span><span class="o">=</span><span class="s2">&quot;^\\[GNUPG:\\] GOODSIG&quot;</span>
</span><span class='line'>
</span><span class='line'><span class="nb">set </span><span class="nv">pgp_timeout</span><span class="o">=</span>9000
</span></code></pre></td></tr></table></div></figure>


<p>For more thorough explanations of the above settings, you can check out the guide that I followed <a href="http://dev.mutt.org/trac/wiki/MuttGuide/UseGPG">here</a></p>

<p>As far as my mutt configuration goes, I added the following lines to my mutt configuration file:</p>

<figure class='code'><figcaption><span>Mutt GPG Config - gpg.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>
</span><span class='line'><span class="nb">bind </span>compose p pgp-menu
</span><span class='line'>
</span><span class='line'><span class="c"># Prepare GPG usage</span>
</span><span class='line'><span class="nb">source</span> ~/.mutt/gpg.rc
</span></code></pre></td></tr></table></div></figure>


<p>The keybinding allows me to hit p after I have composed a message, and it will bring up all of the options I can apply to my mail (sign, encrypt, &#8230;)</p>

<h2>Accessing GMail Contacts</h2>

<p>Another piece of the puzzle was for me to be able to access my gmail contacts through mutt. To do that I leveraged a python utility called <a href="http://code.google.com/p/goobook/">goobook</a>.</p>

<p>Install python if you don&#8217;t already have it:</p>

<figure class='code'><figcaption><span>Install Python - install_python.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>
</span><span class='line'>brew install python
</span></code></pre></td></tr></table></div></figure>


<p>Install goobook:</p>

<figure class='code'><figcaption><span>Install goobook - install_goobook.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>
</span><span class='line'>pip install goobook
</span></code></pre></td></tr></table></div></figure>


<p>To leverage goobook as my contact lookup mechanism, I added the following lines to my mutt configuration file:</p>

<figure class='code'><figcaption><span>Goobook related settings - goobook.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="nb">set </span><span class="nv">query_command</span><span class="o">=</span><span class="s2">&quot;goobook query &#39;%s&#39;&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">editor</span> <span class="o">=</span> <span class="s2">&quot;vim --cmd &#39;let g:goobookrc=\&quot;/Users/jp/.goobookrc\&quot;&#39;&quot;</span>
</span><span class='line'><span class="nb">bind </span>editor &lt;Tab&gt; <span class="nb">complete</span>-query
</span></code></pre></td></tr></table></div></figure>


<p>The first settings tells mutt which utility to use to query for contact completion. The second setting allows me to have vim be able to autocomplete google contacts when I am editing mail headers in Vim. The third setting is just a mutt keybinding that will trigger the goobook search when I hit tab in mail header fields.</p>

<h2>Mail Searching With notmuch</h2>

<p>One of the last pieces of the puzzle was being able to locally search email. I accomplished this by setting up <a href="http://notmuchmail.org/">notmuch</a>. Getting going was as simple as running:</p>

<figure class='code'><figcaption><span>Installing notmuch- not_much_setup.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>brew install notmuch
</span><span class='line'>notmuch setup <span class="c">#setting up for first time use</span>
</span><span class='line'>notmuch new <span class="c">#run the first search</span>
</span></code></pre></td></tr></table></div></figure>


<p>To hook into the search from inside of mutt, I added the following configuration line to my mutt configuration file:</p>

<figure class='code'><figcaption><span>Configuring mutt with notmuch - mutt_not_much.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>macro index S <span class="s2">&quot;&lt;enter-command&gt;unset wait_key&lt;enter&gt;&lt;shell-escape&gt;mutt_notmuch /tempfiles/notmuch_search_results&lt;enter&gt;&lt;change-folder-readonly&gt;/tempfiles/notmuch_search_results&lt;enter&gt;&quot;</span> <span class="s2">&quot;search mail (using notmuch)&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Basically, when I am in mutt and want to search for mail, I can hit S and then enter in a search term. At that point it will shell out to a small ruby script that I wrote, that executes the notmutt search and builds up the appropriate directory structure for mutt to treat the search results as a mail folder that can be explored in mutt. Finally, I change the working folder to the folder containing the search results (for me /tempfiles/notmuch_search_results). Here is the script that I wrote
to do the search and result dir creation:</p>

<figure class='code'><figcaption><span>Searching for mail - mutt_notmuch.rb </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
<span class='line-number'>57</span>
<span class='line-number'>58</span>
<span class='line-number'>59</span>
<span class='line-number'>60</span>
<span class='line-number'>61</span>
<span class='line-number'>62</span>
<span class='line-number'>63</span>
<span class='line-number'>64</span>
<span class='line-number'>65</span>
<span class='line-number'>66</span>
<span class='line-number'>67</span>
<span class='line-number'>68</span>
<span class='line-number'>69</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="c1">#!/usr/bin/env ruby</span>
</span><span class='line'>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;digest/sha1&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;optparse&#39;</span>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;fileutils&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">Hasher</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">initialize</span>
</span><span class='line'>    <span class="vi">@hasher</span> <span class="o">=</span> <span class="no">Digest</span><span class="o">::</span><span class="no">SHA1</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">get_email_hash</span><span class="p">(</span><span class="n">file_name</span><span class="p">)</span>
</span><span class='line'>    <span class="vi">@hasher</span><span class="o">.</span><span class="n">hexdigest</span><span class="p">(</span><span class="no">IO</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">file_name</span><span class="p">))</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">build_results_folder</span><span class="p">(</span><span class="n">results_path</span><span class="p">)</span>
</span><span class='line'>  <span class="no">FileUtils</span><span class="o">.</span><span class="n">rm_rf</span><span class="p">(</span><span class="n">results_path</span><span class="p">)</span>
</span><span class='line'>  <span class="no">FileUtils</span><span class="o">.</span><span class="n">mkdir_p</span><span class="p">(</span><span class="n">results_path</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>  <span class="sx">%w/cur new/</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">folder</span><span class="o">|</span>
</span><span class='line'>    <span class="n">combined_path</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">results_path</span><span class="p">,</span> <span class="n">folder</span><span class="p">)</span>
</span><span class='line'>    <span class="no">FileUtils</span><span class="o">.</span><span class="n">mkdir_p</span><span class="p">(</span><span class="n">combined_path</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">read_line</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
</span><span class='line'>  <span class="nb">print</span> <span class="s2">&quot;Query:&quot;</span>
</span><span class='line'>  <span class="no">STDIN</span><span class="o">.</span><span class="n">gets</span><span class="o">.</span><span class="n">chomp</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_unique_files</span><span class="p">(</span><span class="n">files</span><span class="p">)</span>
</span><span class='line'>  <span class="n">hasher</span> <span class="o">=</span> <span class="no">Hasher</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'>  <span class="n">messages</span> <span class="o">=</span> <span class="p">{}</span>
</span><span class='line'>  <span class="n">files</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span>
</span><span class='line'>    <span class="nb">hash</span> <span class="o">=</span> <span class="n">hasher</span><span class="o">.</span><span class="n">get_email_hash</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
</span><span class='line'>    <span class="n">messages</span><span class="o">[</span><span class="nb">hash</span><span class="o">]</span> <span class="o">=</span> <span class="n">file</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>  <span class="n">messages</span><span class="o">.</span><span class="n">values</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">get_matching_files</span><span class="p">(</span><span class="n">query</span><span class="p">)</span>
</span><span class='line'>  <span class="n">files</span> <span class="o">=</span> <span class="sb">`notmuch search --output=files </span><span class="si">#{</span><span class="n">query</span><span class="si">}</span><span class="sb">`</span>
</span><span class='line'>  <span class="n">files</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">sym_link</span><span class="p">(</span><span class="n">files</span><span class="p">,</span> <span class="n">target_path</span><span class="p">)</span>
</span><span class='line'>  <span class="n">files</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">file</span><span class="o">|</span>
</span><span class='line'>    <span class="nb">system</span><span class="p">(</span><span class="s2">&quot;ln -s </span><span class="si">#{</span><span class="n">file</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">target_path</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="n">results_path</span><span class="p">)</span>
</span><span class='line'>  <span class="n">build_results_folder</span><span class="p">(</span><span class="n">results_path</span><span class="p">)</span>
</span><span class='line'>  <span class="n">query</span> <span class="o">=</span> <span class="n">read_line</span><span class="p">(</span><span class="s2">&quot;Search Phrase?&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">files</span> <span class="o">=</span> <span class="n">get_matching_files</span><span class="p">(</span><span class="n">query</span><span class="p">)</span>
</span><span class='line'>  <span class="n">unique_files</span> <span class="o">=</span> <span class="n">get_unique_files</span><span class="p">(</span><span class="n">files</span><span class="p">)</span>
</span><span class='line'>  <span class="n">sym_link</span><span class="p">(</span><span class="n">unique_files</span><span class="p">,</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">results_path</span><span class="si">}</span><span class="s2">/cur/&quot;</span><span class="p">)</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">parse_arguments</span>
</span><span class='line'>  <span class="no">OptionParser</span><span class="o">.</span><span class="n">new</span> <span class="k">do</span><span class="o">|</span><span class="n">options</span><span class="o">|</span>
</span><span class='line'>    <span class="n">options</span><span class="o">.</span><span class="n">banner</span> <span class="o">=</span> <span class="s2">&quot;Usage is: mutt_notmuch [RESULTS_PATH]&quot;</span>
</span><span class='line'>  <span class="k">end</span><span class="o">.</span><span class="n">parse!</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">path</span> <span class="o">=</span> <span class="no">ARGV</span><span class="o">.</span><span class="n">length</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">?</span> <span class="s2">&quot;/tempfiles/notmuch_search_results&quot;</span> <span class="p">:</span> <span class="no">ARGV</span><span class="o">[</span><span class="mi">0</span><span class="o">]</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">run</span> <span class="n">parse_arguments</span>
</span></code></pre></td></tr></table></div></figure>


<h2>Sending Mail</h2>

<p>Up to this point I have only talked about a scenario optimized for reading mail. One of the main things you will also want to be able to do is send mail. Mutt has support for smtp, but there are more robust programs out there that only focus on smtp. One of those programs is <a href="http://msmtp.sourceforge.net/"> msmtp </a>. This is the program that I configured mutt to use to do mail sending.</p>

<p>Installing is a simple as:</p>

<figure class='code'><figcaption><span>Installing msmtp - msmtp_install.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>brew install msmtp
</span></code></pre></td></tr></table></div></figure>


<p>Here is what my current msmtp configuration file looks like:</p>

<figure class='code'><figcaption><span>Configuring msmtp - msmtp_config.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>account jp
</span><span class='line'>host smtp.gmail.com
</span><span class='line'>port 587
</span><span class='line'>protocol smtp
</span><span class='line'>auth on
</span><span class='line'>from jp@developwithpassion.com
</span><span class='line'>user jp@developwithpassion.com
</span><span class='line'>tls on
</span><span class='line'>tls_trust_file ~/.mutt/equifax_gmail.cert
</span><span class='line'>
</span><span class='line'>account jp_---
</span><span class='line'>host smtp.gmail.com
</span><span class='line'>port 587
</span><span class='line'>protocol smtp
</span><span class='line'>auth on
</span><span class='line'>from jp@developwithpassion.com
</span><span class='line'>user jboodhoo@------
</span><span class='line'>tls on
</span><span class='line'>tls_trust_file ~/.mutt/equifax_gmail.cert
</span><span class='line'>
</span><span class='line'>account default : jp
</span></code></pre></td></tr></table></div></figure>


<p>I &#8220;dashed&#8221; out the information for my current client in the second account configuration. Notice that I am using the first account as the default. In my mutt configuration (for my local mail account), I have the following configuration line for using msmtp as the mail sender:</p>

<figure class='code'><figcaption><span>Mutt msmtp config - mutt_msmtp_config.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="nb">set </span><span class="nv">from</span> <span class="o">=</span> <span class="s2">&quot;jp@developwithpassion.com&quot;</span>
</span><span class='line'><span class="nb">set </span><span class="nv">sendmail</span> <span class="o">=</span> <span class="s2">&quot;/usr/local/bin/msmtp -a jp&quot;</span> <span class="c">#using the account named jp from my msmtp configuration file</span>
</span><span class='line'><span class="nb">set </span><span class="nv">sendmail_wait</span> <span class="o">=</span> 0
</span><span class='line'><span class="nb">unset </span>record <span class="c"># gmail records sent mail automatically, so we don&#39;t need to track</span>
</span></code></pre></td></tr></table></div></figure>


<p>I have 2 aliases set up that allow me to start mutt with my local mail account, and the other for my client mail account. Each instance uses a client specific mutt configuration that is also configured with the correct msmtp account to use for sending. That is outside of the scope of this article, but it is just a matter of templates and aliases.</p>

<h2>Handling mail attachments</h2>

<p>One of the first snags I ran into was correctly handling mail that contained attachments (sending mail with attachments is a snap, so I won&#8217;t go into it in this article). By defaualt, mutt will use you <a href="http://en.wikipedia.org/wiki/Mailcap"> mailcap </a> file to try to determine how to handle email. The contents of my mailcap file look as follows:</p>

<figure class='code'><figcaption><span>Mailcap file - mailcap.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'><span class="c"># MS Office files</span>
</span><span class='line'>application/msword; ~/.mutt/view_mail_attachment.rb --file:%s --type:<span class="s2">&quot;-&quot;</span> --open_with:<span class="s1">&#39;/Applications/OpenOffice.org.app&#39;</span>
</span><span class='line'>application/vnd.ms-excel; ~/.mutt/view_mail_attachment.rb --file:%s --type:<span class="s2">&quot;-&quot;</span>
</span><span class='line'>application/vnd.openxmlformats-officedocument.presentationml.presentation; ~/.mutt/view_mail_attachment.rb --file:%s --type:<span class="s2">&quot;-&quot;</span> --open_with:<span class="s1">&#39;/Applications/OpenOffice.org.app&#39;</span>
</span><span class='line'>application/vnd.oasis.opendocument.text; ~/.mutt/view_mail_attachment.rb --file:%s --type:<span class="s2">&quot;-&quot;</span> --open_with:<span class="s1">&#39;/Applications/OpenOffice.org.app&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="c"># Images</span>
</span><span class='line'>image/jpg; ~/.mutt/view_mail_attachment.rb --file:%s --type:jpg
</span><span class='line'>image/jpeg; ~/.mutt/view_mail_attachment.rb --file:%s --type:jpg
</span><span class='line'>image/pjpeg; ~/.mutt/view_mail_attachment.rb --file:%s --type:jpg
</span><span class='line'>image/png; ~/.mutt/view_mail_attachment.rb --file:%s --type:png
</span><span class='line'>image/gif; ~/.mutt/view_mail_attachment.rb --file:%s --type:gif
</span><span class='line'>
</span><span class='line'><span class="c"># PDFs</span>
</span><span class='line'>application/pdf; ~/.mutt/view_mail_attachment.rb --file:%s --type:pdf
</span><span class='line'>
</span><span class='line'><span class="c"># HTML</span>
</span><span class='line'>text/html; ~/.mutt/view_mail_attachment.rb --file:%s --type:html
</span><span class='line'>
</span><span class='line'><span class="c"># Unidentified files</span>
</span><span class='line'>application/octet-stream; ~/.mutt/view_mail_attachment.rb --file:%s --type:<span class="s2">&quot;-&quot;</span>
</span></code></pre></td></tr></table></div></figure>


<p>Notice that most of this script shells out to a custom ruby script that does the appropriate program launching. Here is that script:</p>

<figure class='code'><figcaption><span>View Mail Attachment - view_mail_attachment.rb </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
<span class='line-number'>53</span>
<span class='line-number'>54</span>
<span class='line-number'>55</span>
<span class='line-number'>56</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="c1">#!/usr/bin/env ruby</span>
</span><span class='line'>
</span><span class='line'><span class="nb">require</span> <span class="s1">&#39;fileutils&#39;</span>
</span><span class='line'>
</span><span class='line'><span class="k">class</span> <span class="nc">Arguments</span>
</span><span class='line'>  <span class="kp">attr_accessor</span> <span class="ss">:file</span>
</span><span class='line'>  <span class="kp">attr_accessor</span> <span class="ss">:type</span>
</span><span class='line'>  <span class="kp">attr_accessor</span> <span class="ss">:open_with</span>
</span><span class='line'>  <span class="kp">attr_accessor</span> <span class="ss">:temp_dir</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">temp_dir</span>
</span><span class='line'>    <span class="vi">@temp_dir</span> <span class="o">||=</span> <span class="s2">&quot;/tempfiles/mutt_attachments&quot;</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">base_file_name</span>
</span><span class='line'>    <span class="vi">@base_file_name</span> <span class="o">||=</span> <span class="no">File</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">file</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">def</span> <span class="nf">base_file_name_without_extension</span>
</span><span class='line'>    <span class="no">File</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">base_file_name</span><span class="p">,</span> <span class="no">File</span><span class="o">.</span><span class="n">extname</span><span class="p">(</span><span class="n">base_file_name</span><span class="p">))</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="k">def</span> <span class="nf">build_arguments</span><span class="p">(</span><span class="n">arguments</span><span class="p">)</span>
</span><span class='line'>  <span class="n">result</span> <span class="o">=</span> <span class="no">Arguments</span><span class="o">.</span><span class="n">new</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">arguments</span><span class="o">.</span><span class="n">each</span> <span class="k">do</span><span class="o">|</span><span class="n">argument</span><span class="o">|</span>
</span><span class='line'>    <span class="n">pair</span> <span class="o">=</span> <span class="n">argument</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;:&quot;</span><span class="p">)</span>
</span><span class='line'>    <span class="nb">name</span> <span class="o">=</span> <span class="n">pair</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="n">gsub</span><span class="p">(</span><span class="sr">/-/</span><span class="p">,</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
</span><span class='line'>    <span class="n">value</span> <span class="o">=</span> <span class="n">pair</span><span class="o">[</span><span class="mi">1</span><span class="o">]</span>
</span><span class='line'>    <span class="n">result</span><span class="o">.</span><span class="n">send</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="nb">name</span><span class="si">}</span><span class="s2">=&quot;</span><span class="p">,</span> <span class="n">value</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>  <span class="n">result</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">arguments</span> <span class="o">=</span> <span class="n">build_arguments</span><span class="p">(</span><span class="no">ARGV</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nb">system</span><span class="p">(</span><span class="s2">&quot;mkdir -p </span><span class="si">#{</span><span class="n">arguments</span><span class="o">.</span><span class="n">temp_dir</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'><span class="nb">system</span><span class="p">(</span><span class="s2">&quot;rm -rf </span><span class="si">#{</span><span class="n">arguments</span><span class="o">.</span><span class="n">temp_dir</span><span class="si">}</span><span class="s2">/*&quot;</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'>
</span><span class='line'><span class="n">new_file_name</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="n">arguments</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s2">&quot;-&quot;</span><span class="p">)</span>
</span><span class='line'>  <span class="n">new_file_name</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">basename</span><span class="p">(</span><span class="n">arguments</span><span class="o">.</span><span class="n">file</span><span class="p">)</span>
</span><span class='line'><span class="k">else</span>
</span><span class='line'>  <span class="n">new_file_name</span> <span class="o">=</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">arguments</span><span class="o">.</span><span class="n">base_file_name_without_extension</span><span class="si">}</span><span class="s2">.</span><span class="si">#{</span><span class="n">arguments</span><span class="o">.</span><span class="n">type</span><span class="si">}</span><span class="s2">&quot;</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">new_file_name</span> <span class="o">=</span> <span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">arguments</span><span class="o">.</span><span class="n">temp_dir</span><span class="p">,</span> <span class="n">new_file_name</span><span class="p">)</span>
</span><span class='line'><span class="no">FileUtils</span><span class="o">.</span><span class="n">cp</span> <span class="n">arguments</span><span class="o">.</span><span class="n">file</span><span class="p">,</span> <span class="n">new_file_name</span>
</span><span class='line'>
</span><span class='line'><span class="k">if</span> <span class="p">(</span><span class="n">arguments</span><span class="o">.</span><span class="n">open_with</span><span class="p">)</span>
</span><span class='line'>  <span class="nb">system</span><span class="p">(</span><span class="s2">&quot;open -a </span><span class="si">#{</span><span class="n">arguments</span><span class="o">.</span><span class="n">open_with</span><span class="si">}</span><span class="s2"> </span><span class="si">#{</span><span class="n">new_file_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'><span class="k">else</span>
</span><span class='line'>  <span class="nb">system</span><span class="p">(</span><span class="s2">&quot;open </span><span class="si">#{</span><span class="n">new_file_name</span><span class="si">}</span><span class="s2">&quot;</span><span class="p">)</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>As you can see, this solution makes the assumption that I write attachments to the following folder : /tempfiles/mutt_attachments</p>

<h2>Conclusion</h2>

<p>It took a couple of days for me to tweak my keybindings and customize my setup.  After the initial rampup, I love that I can now compose, read, edit my email in Vim, here is a <a href="https://www.evernote.com/shard/s52/sh/aac37c0a-93d4-4725-b06e-568a116d0275/debdc82b2efcbd43033a426eeb6fb66f/deep/0/2013-05-02%201:48%20PM.png">screenshot</a> of what my gtd window in tmux looks like:</p>

<p><img src="https://www.evernote.com/shard/s52/sh/aac37c0a-93d4-4725-b06e-568a116d0275/debdc82b2efcbd43033a426eeb6fb66f/deep/0/2013-05-02%201:48%20PM.png" title="Tmux GTD Pane" ></p>

<p>Needless to say, the screenshot says it all (from my perspective!!)</p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Game Crash Bootcamp Coming To Calgary In May!!!]]></title>
    <link href="http://blog.developwithpassion.com/2013/03/27/game-crash-bootcamp-coming-to-calgary-in-may/"/>
    <updated>2013-03-27T07:47:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2013/03/27/game-crash-bootcamp-coming-to-calgary-in-may</id>
    <content type="html"><![CDATA[<p>The <a href="http://www.developwithpassion.com/training/game_crash">Develop With Passion® - Game Crash Bootcamp</a> is coming to Calgary, AB, Canada on the week of the 27th May 2013.</p>

<p>The course will be led by the extremely skilled Jon Beltran de Heredia, and it will be held at the Residence Inn Marriott Airport.</p>

<p>Attendees of the first Game Crash Bootcamp in Austin, back in February, were blown away by the course content. Jon has worked hard to develop a curriculum that can ensure that developers are able to build the skills to feel confident building games from scratch by the end of the week.</p>

<p>As with all Develop With Passion® courses, the focus is on fundamentals. Nothing shiny here. Nuts and bolts, math, and programming techniques that are not going to fade away with platform changes and language changes.</p>

<p>Develop With Passion® has always strived to go &#8220;deep&#8221; with students. I personally feel that if more developers allowed themselves to really understand concepts, instead of just &#8220;Google/Stack Overflow -> Copy -> Paste&#8221;, that they would utlimately feel much more confident about their abilities as a coder. Jon shares my approach to this, which is why he is the perfect trainer for this course.</p>

<p>If you have ever had a desire to want to learn game programming. This course will teach you the math, programming, and war stories from someone who has built very popular games for different hardware platforms.</p>

<p>Along with the onsite course which will be held at the Residence Inn Marriott Airport, in Calgary. The course will also be offered for people to attend remotely via a gotomeeting setup. This will give people who can&#8217;t fly to Calgary a change to take the course in their PJ&#8217;s if they so wish.</p>

<p>The price breakdown for this new offering (prices are only applicable for this year, next year the price will most likely rise to match the regular Develop With Passion® bootcamps):</p>

<ul>
<li>Onsite US &amp; Canada: $2500</li>
<li>Onsite International: $3500</li>
<li><p>Remote: $1500</p></li>
<li><p>Early bird discount (Registering within 2 weeks of event being published): $500</p></li>
</ul>


<p>For more information on the course go <a href="http://developwithpassion.com/training/game_crash"> here </a>. To register you can use one of the following links:</p>

<ul>
<li><a href="http://dwp-gamecrash-2013-may-calgary.eventbrite.com/"> Calgary Onsite </a></li>
<li><a href="http://dwp-gamecrash-2013-may-remote.eventbrite.com/"> Calgary Remote </a></li>
</ul>


<p>Jon and I both feel confident that this is going to become a hugely popular course, once more people participate and realize how empowered they will feel with the results they will come up with in one week!!</p>

<p><a href="http://www.developwithpassion.com"> Develop With Passion® </a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Do Everything]]></title>
    <link href="http://blog.developwithpassion.com/2013/03/27/do-everything/"/>
    <updated>2013-03-27T07:36:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2013/03/27/do-everything</id>
    <content type="html"><![CDATA[<p>Fell in love with this song quite a while ago. Thought I would share it here, to hopefully give you a boost for the day!! You might not love the video style (I think it&#8217;s pretty creative), but really listen to the words and let it remind you that everything we do matters.</p>

<p>&#8220;Do everything you do to the glory of the one who made you!!&#8221;</p>

<script type="text/javascript" src="http://www.godtube.com/embed/source/f9b20cnu.js?w=500&h=400&ap=false&sl=true&title=true"></script>


<p><a href="http://www.godtube.com/watch/?v=F9B20CNU">Steven Curtis Chapman - Do Everything (Official Music Video)</a> from <a href="http://www.godtube.com/steven-curtis-chapman">steven-curtis-chapman</a> on <a href="http://www.godtube.com/">GodTube</a>.</p>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Pursuing Mastery]]></title>
    <link href="http://blog.developwithpassion.com/2013/03/01/pursuing-mastery/"/>
    <updated>2013-03-01T09:00:00-07:00</updated>
    <id>http://blog.developwithpassion.com/2013/03/01/pursuing-mastery</id>
    <content type="html"><![CDATA[<p>It occurred to me a couple of years ago, that there really is no such thing as attaining mastery of software development. We are all just at different stages of beginning.</p>

<p>When I was running a Software Craftmanship bootcamp in the UK a couple of years one of the attendees was kind enough to give me a copy of the book Bushido - The Way of the Samurai. He felt that a lot of the concepts that I was both demonstrating and talking about, were reflected in a lot of the ideas in the book. It really is a fantastic book on the subject of &#8220;pursuing mastery&#8221;. Software developers in general spend a lot of time trying to &#8220;attain mastery&#8221;. The only problem with this endeavour
is that they can often trick themselves into falsely feeling like they have &#8220;attained it&#8221;. This can often result in the following set of events happening:</p>

<ul>
<li>Establishing themselves as a subject matter expert in one or more areas</li>
<li>Camping on their ideas for a long period of time.</li>
<li>Failure to want to be &#8220;the beginner&#8221; again, as they have worked hard to be perceived as an expert</li>
<li>Boredom, as their need to hang-on prevents them from moving ahead</li>
<li>Transitioning to management as the next logical step, more because they come to realize that their skills have atrophied</li>
</ul>


<p>Of course, that little blurb above is a very generalized path, but one that I have been able to observe enough for it to not just be an accident.</p>

<p>The sooner we can start realizing that we &#8220;pursue&#8221; mastery, then we will realize that the learning never stops.  We don&#8217;t need to pat ourselves on the back too long when we have made an accomplishment, we can focus on incremental, iterative growth over the entirety of our career. This is the kind of movement that can prevent boredom, stagnation and the unecessary &#8220;promotion&#8221; to management. Now let me be clear, I have no issue with programmers who make the move to management because they
choose and have a desire to.  I am speaking to the devs who made the move because they felt like they had no other progression paths.</p>

<p>Here is an excerpt from the Bushido book that sums up what I am trying to say:</p>

<h1><blockquote><p>An old, retired swordsman once said, &#8220;There are levels in the course of mastery throughout your life. At the lowest level of skill and ability, one thinks of himself and others as poor.  He thinks this because he has mastered only a little.  Needless to say, a person at this level is not at all useful.  &#8221;<br/>&#8220;At the middle level, one is still useless, but he can at least understand that he and others have mastered only a little.&#8221;<br/>&#8220;At a high level, since a person has made something his own, he is proud of his accomplishment.  And he is also glad of the praise of others.  He grieves over the shortcomings of others.  This kind of person is at least useful.&#8221;<br/>At a higher level, one pretends to know nothing, yet others understand that he holds an upper hand.  The majority of people cannot get beyond this level.<br/>Beyond this higher level, there is one further step: the level of the trackless road.  If you travel deeper into the trackless road, infinite secrets will finally appear.  Then you can never see the end of your mastery.  Then you truly realize how lacking you are.  You have only to go ahead with your intention of mastery in mind.  You go forward without pride and without humility.</p><footer><strong>High Upon High</strong> <cite>Bushido - the Way of the Samurai</cite></footer></blockquote></h1>

<p>Favourite part of the excerpt:</p>

<h1><blockquote><p>Then you can never see the end of your mastery.  Then you truly realize how lacking you are.  You have only to go ahead with your intention of mastery in mind.  You go forward without pride and without humility.</p></blockquote></h1>

<p>I pray that you can continue to enjoy the pursuit!!</p>

<p><a href="http://www.developwithpassion.com"> Develop With Passion® </a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Where Should We Host The Next Gamecrash Bootcamp?]]></title>
    <link href="http://blog.developwithpassion.com/2013/02/28/where-should-we-host-the-next-gamecrash-bootcamp/"/>
    <updated>2013-02-28T07:00:00-07:00</updated>
    <id>http://blog.developwithpassion.com/2013/02/28/where-should-we-host-the-next-gamecrash-bootcamp</id>
    <content type="html"><![CDATA[<p>It has been one week since the first <a href="http://www.developwithpassion.com/training/game_crash"> Gamecrash Bootcamp </a> completed. It was a great success and we are already in the midst of planning and refining based on feedback from this first iteration!</p>

<p>Currently, the next big question to ask and answer is where the next course should be hosted?</p>

<p>Instead of us just arbitrarily picking the next location, we thought we would solicit some suggestions on where the course should go next. To that end, if you feel compelled to help drive the literal direction of this course, please respond to the following survey, to help us make our decision!</p>

<p>We are looking forward to bringing this amazing bootcamp to developers all over the world who are wanting to stop just &#8220;thinking&#8221; about writing a game, and give them the fundamental skills and knowledge with which they can actually &#8220;write&#8221; one. We are also hoping to demystify for lots of developers, what it means to do things like:</p>

<ul>
<li>Write your own physics engine</li>
<li>Leveraging OpenGL for graphics primitives</li>
<li>lots, lots more&#8230;!!!</li>
</ul>


<iframe src="http://www.surveymonkey.com/s/7F5K5KV" width="100%" height="700"></iframe>


<p><a href="http://www.developwithpassion.com"> Develop With Passion® </a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Be Willing To Become The Beginner Again]]></title>
    <link href="http://blog.developwithpassion.com/2013/02/07/be-willing-to-become-the-beginner-again/"/>
    <updated>2013-02-07T08:40:00-07:00</updated>
    <id>http://blog.developwithpassion.com/2013/02/07/be-willing-to-become-the-beginner-again</id>
    <content type="html"><![CDATA[<p>I have been a software developer for just over 12 years. Not a crazy long period of time, but long enough to have learned a couple of lessons!</p>

<p>In that time God has blessed me with the opportunity to work in a whole host of development environments, business domains, and countries.  One of the things that I am constantly trying to do is push and stay outside of comfort zones. This is a life principal that is not just localized to the realm of my career. God does not want you to camp in a comfort zone, you can&#8217;t grow in a comfort zone. You can only maintain.</p>

<p>For the majority of my consulting gigs I have been able to experience a very high degree of success and leave with glowing reviews from both the managers and developers that I spend
my time with. As a developer my primary focus when engaging clients, has been to focus on the code side of the fence. That is where my work passion lives. I am not interested in iteration management or project management. Having this knowledge has allowed me to maintain a very high degree of focus in honing the &#8220;craft&#8221;.</p>

<p>As a perpetual student, I am constantly welcoming of the opportunity to work with teams and individuals of all skill levels. In this capacity, I have historically been brought in as a senior resource to help cut some crazy code. It has been a while, but for the first time in a long time, the current contract that I am on has me feeling like a complete beginner again!!</p>

<p>And I will tell you the truth, it is times like this when I am reminded at an even higher level, of how exciting the realm of software development is. I love having my ideas turned upside down, and even in the span of only one month (the contract just started 1 month ago), I am actively and happily questioning, and shifting a lot of the approaches that I have taken to developing software, and more importantly design in general!!</p>

<p>Every morning for the last 5 years, I have woke up and thanked God for the fact that my career was starting again, that very day. When you wake up in the morning you get to choose how you are going to react to the events that come along in your day. You get to choose to be the beginner again. To realize that what you know now can become a small fragment of what you will know in a month, a year, a decade.</p>

<p>If you let go any assumptions you have about your own skill level, and go forward with the &#8220;pursuit&#8221; and not attainment of mastery; every day will be an amazing opportunity to tap into the creativity of the One who created us to be creative. You can choose joy, choose to be thankful, and choose to make a difference in not just your attitude and approach, but of those you surround yourself with.</p>

<p>Thank you Lord for allowing me to start my career again today!! I choose the path of the beginner.</p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[2013 Course Schedule]]></title>
    <link href="http://blog.developwithpassion.com/2013/01/08/2013-course-schedule/"/>
    <updated>2013-01-08T23:04:00-07:00</updated>
    <id>http://blog.developwithpassion.com/2013/01/08/2013-course-schedule</id>
    <content type="html"><![CDATA[<p>The Develop With Passion® 2013 course schedule is now <a href="http://developwithpassion.eventbrite.com">online</a>!</p>

<p>Currently the course load is small, but you can expect to see additions as Jon and I coordinate further iterations of the <a href="http://www.developwithpassion.com/training/game_crash">Gamecrash</a> bootcamp over the course of the year.</p>

<p>Personally, I will be hosting courses in the following locations:</p>

<ul>
<li>Calgary,AB</li>
<li>Denver, CO</li>
<li>San Diego, CA</li>
<li>Manchester, UK</li>
<li>Brussels, Belgium</li>
<li>Nashville, TN</li>
<li>Philadelphia, PA</li>
<li>Edmonton, AB</li>
</ul>


<p>This year I will also be mixing in more occurences of the Ruby Primer bootcamp, as the first iteration proved to be very successful.</p>

<p>With the <a href="http://jonbho.net/2012/12/25/gamecrash-new-hyper-intensive-game-development-boot-camps/">announcement</a> that Jon made about the Gamecrash bootcamp, we are looking forward to a flood of new students excited to get into the world of game programming.</p>

<p>Develop With Passion® looks forward, and is honoured, to be a part in kickstarting/reginiting the passion in the 2013 class!!</p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[New Course Announcement - Gamecrash Bootcamp]]></title>
    <link href="http://blog.developwithpassion.com/2012/12/21/new-course-announcement-gamecrash-bootcamp/"/>
    <updated>2012-12-21T13:57:00-07:00</updated>
    <id>http://blog.developwithpassion.com/2012/12/21/new-course-announcement-gamecrash-bootcamp</id>
    <content type="html"><![CDATA[<p>I am happy to announce that Develop With Passion® is adding a new course to its roster of kick butt one of a kind developer training. <a href="http://www.developwithpassion.com/training/game_crash">Develop With Passion® - Gamecrash Bootcamp</a> is a course focused on taking traditional developers with no prior experience in game programming and having them come out at the end of the week with the fundamental skills required to build games.</p>

<p>As all Develop With Passion® courses, the primary focus will be on the fundamentals. We want to give you the core tools that you can use to apply in any environment that you may consider building games.</p>

<p>As time permits I will make myself available to deliver this course also, but this brings me to the other part of this exciting announcement!</p>

<p>The primary instructor for this course is going to be <a href="http://jonbho.net/">Jon Beltran de Heredia</a>, who many of you know as the creator of the fantastic <a href="http://www.viemu.com/">ViEmu</a>. Jon has a long history with game programming, being the lead programmer for Commandos and Commandos 2, and has deep experience with all aspects of game development.</p>

<p>We are very excited to have Jon on board with Develop With Passion®, and can&#8217;t wait to have a whole new set of students get &#8220;put through the wringer&#8221;!!</p>

<p>Please join me in welcoming Jon to the Develop With Passion® team and Gamecrash to the awesome lineup of courses that Develop With Passion® is continuing to grow.</p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Happy to report - First public Ruby course is a smash!!]]></title>
    <link href="http://blog.developwithpassion.com/2012/12/17/happy-to-report-first-public-ruby-course-a-smash/"/>
    <updated>2012-12-17T09:00:00-07:00</updated>
    <id>http://blog.developwithpassion.com/2012/12/17/happy-to-report-first-public-ruby-course-a-smash</id>
    <content type="html"><![CDATA[<p>Just a quick post to share the fact that the first <a href="http://developwithpassion.com/training/ruby/primer_bootcamp">Ruby Primer Bootcamp</a> that was held in Las Vegas last month was a huge success!!</p>

<p>Considering that the group was extremely small (2 people!, not a surprise for the first run) , and that they both had experience with ruby (1 - 3 years), the challenge level received was significant and there was lots of amazing feedback. This feedback has strengthened my resolve to take this officially on the road as there is lots for even seasoned Ruby devs to learn.</p>

<p>The plan will be to deliver more of the Ruby Primer Bootcamps next year along with continuing to deliver the Develop With Passion - .Net Bootcamp.</p>

<p>My hope is that as awareness of the course and its challenging content grows, word of mouth will circulate and the class sizes will start to get bigger, which ultimately makes it a much richer environment for learning.</p>

<p>Here are some journal notes made by the attendees of the course:</p>

<ul>
<li><a href="http://mokhan.ca/journal/2012/12/09/software-craftsmanship.html">software craftmanship</a></li>
<li><a href="http://mokhan.ca/journal/2012/12/13/level-up.html">level up</a></li>
</ul>


<blockquote><p>Having already done the .Net boot camp I was looking forward to the Ruby Primer course with lots of excitement and a little bit of fear. Excitement because I knew how much I&#8217;d be learning over the course of the week and fear because it was going to be lots of hard work. It was totally worth it, embrace the fear!</p><p>I love playing around with Ruby and naively thought I had a pretty good grasp of the language but that idea was wiped out on day one. The course takes you out of your comfort zone very quickly and this is where real growth happens.</p><p>JP&#8217;s method of teaching brings the theory and practice of the ruby fundamentals together in such a way that it really sinks in. I have been genuinely surprised at how much more I understand some of the gnarly meta programming code I&#8217;ve read since the course. Before the course the same code would have just made my eyes glaze over.</p><p>I would have no hesitation recommending this course to anyone, Ruby programmer or not as long as you have a genuine interest in becoming better at your craft. Seeing the patterns and practices attacked from another angle, Ruby rather than .Net has really helped my understanding and at the same time highlighted gaps in my knowledge.  JP&#8217;s boot camps are not really a weeklong, they last for weeks, months, and years as you try and plug these gaps.</p><p>It wasn&#8217;t all about the technical, as well as keeping you incredibly well fed and watered the course also leads you to do some real soul searching about where your career and even life in general is heading.</p><p>Thank you JP for a truly life changing experience! Now how many &#8216;technical&#8217; courses do you get to say that about?</p><footer><strong>Justin Ramel</strong> <cite>Develop With Passion® Alumni</cite></footer></blockquote>


<p>I feel blessed to be able to reach another set of developers with a set of approaches and techniques that do truly transcend language and platforms!</p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Start Shining With Ruby - Camug Presentation Next Saturday]]></title>
    <link href="http://blog.developwithpassion.com/2012/10/27/start-shining-with-ruby-next-saturday/"/>
    <updated>2012-10-27T13:00:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/10/27/start-shining-with-ruby-next-saturday</id>
    <content type="html"><![CDATA[<p>Well, its been quite a long time since I have given a formal presentation!!</p>

<p>The guys at <a href="http://www.meetup.com/Calgary-Agile-Methods-User-Group/events/87125652/">camug</a> graciously asked if I would be interested in coming to give a small 4 hour intro to the Ruby programming language.</p>

<p>I am going to keep the concepts as simple as possible; and treat it as a basic introduction to the ruby programming language in the context of building a simple, but fun, application.</p>

<p>The presentation is completely free so if you are interested in attending you have to:</p>

<ul>
<li>Register for the event at the camug site (there are only 25 spots available)</li>
<li>Show up next Saturday morning with you laptop in tow, so that you can code along and have the concepts solidify in your head.</li>
</ul>


<h2>Software Requirements</h2>

<ul>
<li><p>Windows Based OS</p>

<ul>
<li>Install the latest version of Ruby using the <a href="http://rubyforge.org/frs/download.php/76527/rubyinstaller-1.9.3-p286.exe">RubyInstaller</a></li>
</ul>
</li>
<li><p>Unix Based OS (OSX/Linux)</p>

<ul>
<li>Install the most current version of <a href="https://rvm.io/rvm/install/">RVM</a>, using the instructions on its site.</li>
</ul>
</li>
</ul>


<p>Regardless of which environment you come with, make sure that you have it configured correctly and can run a basic ruby file from your console. I would also recommend that you have a good text editor at the ready to code along during the presentation.</p>

<p>If there are still spots available, come out for what I pray will be a fun even for all involved!!!</p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Still Time To Register For The London Software Craftmanship BootCamp]]></title>
    <link href="http://blog.developwithpassion.com/2012/08/23/still-time-to-register-for-the-london-software-craftmanship-bootcamp/"/>
    <updated>2012-08-23T13:00:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/08/23/still-time-to-register-for-the-london-software-craftmanship-bootcamp</id>
    <content type="html"><![CDATA[<p>Time is fast approaching for the next iteration of the Develop With Passion® Software Craftmanship BootCamp to be held in London,UK (September 10-14th).</p>

<p>Once again, this year we will be hosting the course at the Ramada Hyde Park. Registration details can be found <a href="http://www.eventbrite.com/event/1570733105/eorg">here</a>.</p>

<p>You can come expecting 5 fun filled days of coding madness. Come and learn fundamental software principles, patterns, and techniques that will help take you to the next level in your career as a computer programmer. The course will be using .Net as a delivery mechanism, but past students will iterate that the course really has nothing to do with .Net. It is a walkthrough of practical application design techiques and approaches that you can use regardless of what your primary
development environment/platform is.</p>

<p>If you are up for a challenge, or you feel like your dev routine needs a bit of a kick in the pants, sign up for what many others have called a &#8220;game-changer&#8221; in both their life and career.</p>

<p>I look forward to seeing you <a href="http://www.eventbrite.com/event/1570733105/eorg">there</a>!</p>

<p><a href="http://www.eventbrite.com/event/1570733105/eorg">Register Now</a></p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Screencast: Leveraging Keymando's Hit-A-Hint style feature for clicking/pressing ui elements]]></title>
    <link href="http://blog.developwithpassion.com/2012/07/16/screencast-leveraging-keymandos-hit-a-hint-style-feature-for-clicking-slash-pressing-ui-elements/"/>
    <updated>2012-07-16T20:42:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/07/16/screencast-leveraging-keymandos-hit-a-hint-style-feature-for-clicking-slash-pressing-ui-elements</id>
    <content type="html"><![CDATA[<p>In this screencast I walk you through the awesome (and yet still not very well known) feature of being able to have Keymando highlight elements that you want to act on (typically by left clicking, double clicking etc) in a user interface and then trigger them by typing in the identifier.</p>

<p>If you have ever used Pentadactyl or Vimperator, you are already familiar with the feature. In Pentadactyl, when a web page is being displayed, if you press the &#8216;f&#8217; key, it will highlight all of the clickable links on the page. To click a link, you just have to type in the digits/letters that correspond to the link. As you can imagine, this feature can save quite a lot of time!!</p>

<p>Well, Keymando supports the same style of feture, except you can use it in any OSX based app that supports OSX Accessibility.</p>

<p>In the screencast I show you a sample usage scenario of this awesome feature!</p>

<iframe src="http://player.vimeo.com/video/45875994 " width='400' height='255' frameborder='0' webKitAllowFullScreen mozillallowfullscreen allowFullScreen></iframe>


<p>Go <a href="http://updates.Keymando.com">here</a> to get the latest version of Keymando, and get busy automating your way through OSX!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Get Ready For The Upcoming Develop With Passion® 2012 Courses!!]]></title>
    <link href="http://blog.developwithpassion.com/2012/07/14/get-ready-for-the-upcoming-develop-with-passion%28r%29-2012-course-roster/"/>
    <updated>2012-07-14T15:16:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/07/14/get-ready-for-the-upcoming-develop-with-passion(r)-2012-course-roster</id>
    <content type="html"><![CDATA[<p>I am in the last 2 months of an awesome contract that I was blessed to work on this year. We are now getting prepared for what I am sure is going to be an amazing lineup of courses, to be held over the remainder of the 2012 calendar year.</p>

<p>Along with a set of tried and tested: Develop With Passion® - .Net Bootcamps, this year I am also going to be launching a Develop With Passion® - Ruby Bootcamp! In the same vein as the .Net bootcamp, this course will be a deep dive into advanced fundamentals of software engineering using Ruby as the delivery language mechanism. Over the course of the week, you will learn the ins an out of design patterns, software engineering, automated testing and builds, all while trying to build a Rails clone from the ground up. If you are wanting yet another course that will teach you how to use Rails - well, this one won&#8217;t be for you. This is a course that (like
the .Net bootcamp) is geared at making you a much better software developer overall. Of course we will dive into some pretty awesome usages of the language and it capabilities, but first and foremost these bootcamps are all about giving you a solid foundation with which you can use to propel your software goals to new heights.</p>

<p>One of the biggest changes I am personally making to the courses (based off of a couple of years worth of feedback now) is the addition of slide decks to complement the material that is covered. This has traditionally been a very code focused course set, with the majority of the five 12 hours days that make up a course week revolving around cutting code! That focus is not changing, but it is now going to be augmented with a set of material that will cater to the visual learners.</p>

<p>The automation for the course over the years has become really smooth. With <a href="http://github.com">GitHub</a> being used as a central component for both versioning our changes, as well as rapidly switching between different views on a problem. Even if you have no git experience, the automation scripts that are setup for the course allow people to keep moving smoothly without git inexperience getting in the way.</p>

<p>Course weeks are recorded in ScreenFlow screencasting software, and students are able to copy the screencasts from me at the end of the course week.</p>

<p>Over the course of the past 4 years I have been blessed to be able to travel the world with my family and deliver this course to over 1500 people. Over that time, I have had the benefit of identifying patterns and practices of effective development that I have both observed from people I have worked with as well as effective devs who have taken the training course. My main personal goals for anyone attending one of the Develop With Passion® courses are as follows:</p>

<ol>
<li>Provide you with approaches, resources, and examples that can help turn you into an amazing coder.</li>
<li>Give inspiration and insight that can help you set bigger goals both professionally and more importantly, personally.</li>
<li>Help you to remember why you became a coder in the first place.</li>
</ol>


<p>Don&#8217;t take my word for it, here is a sampling of comments made by past students (good and bad!, sorry for the age of the links, collecting reviews has definitely been a weak point!):</p>

<ul>
<li><a href="http://blog.developwithpassion.com/2008/12/11/so-what-do-past-students-really-think-about-nothin-but-net/">So What Do Past Students Really Think</a></li>
</ul>


<p>The upcoming course schedule for the 2012 year can be seen <a href="http://developwithpassion.eventbrite.com">here</a>.</p>

<p>And just in case you don&#8217;t click on the link, here it is:</p>

<ul>
<li><a href="http://dwpnewyork2012-eorg.eventbrite.com/">.Net Bootcamp - New York, NY - 27/8/2012</a></li>
<li><a href="http://www.eventbrite.com/event/1570733105/eorg">.Net Bootcamp - London, UK - 10/9/2012</a></li>
<li><a href="http://developwithpassion_brussels_2012-eorg.eventbrite.com/">.Net Bootcamp - Brussel, Belgium - 17/9/2012</a></li>
<li><a href="http://dwpchicago2012-eorg.eventbrite.com/">.Net Bootcamp - Chicago, IL - 1/10/2012</a></li>
<li><a href="http://www.eventbrite.com/event/3625225146/eorg">.Net Bootcamp - Remote - 15/10/2012</a></li>
<li><a href="http://developwithpassion-calgary2012-eorg.eventbrite.com/">.Net Bootcamp - Calgary, AB - 5/11/2012</a></li>
<li><a href="http://www.eventbrite.com/event/3614317521/eorg">Ruby Bootcamp - Las Vegas, NV - 26/11/2012</a></li>
<li><a href="http://www.eventbrite.com/event/3043849235/eorg">.Net Bootcamp - Edmonton, AB - 3/12/2012</a></li>
</ul>


<p>I am pretty excited about the courses that are coming up, and look forward to seeing some new faces ready to learn and share together!</p>

<p>Come and learn how to <a href="http://www.developwithpassion.com">Develop With Passion®</a></p>

<p>God Bless You!</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[fakes - New Feature - Swapping Classes (useful for class methods)]]></title>
    <link href="http://blog.developwithpassion.com/2012/06/11/fakes-new-feature-swapping-classes-useful-for-class-methods/"/>
    <updated>2012-06-11T08:26:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/06/11/fakes-new-feature-swapping-classes-useful-for-class-methods</id>
    <content type="html"><![CDATA[<p>Just added another new feature to <a href="http://github.com/developwithpassion/fakes">fakes</a> to support something I was doing.</p>

<p>The feature in question is the ability to swap out classes at test time. The most useful aspect for this is in both configuring and monitoring calls made to class methods. Up until now, I have just used the rspec (predominant testing library I use) out of box mechanism to do this. With this feature added now, I don&#8217;t need to use any of the out of box rspec mocking features.</p>

<p>Here is an example of using the capability to monitor a call made to delete a file:</p>

<figure class='code'><figcaption><span>Monitoring a call made to the File class - class_swapping_example_1.rb </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="k">class</span> <span class="nc">DeleteFileCommand</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">filename</span><span class="p">)</span>
</span><span class='line'>    <span class="vi">@filename</span> <span class="o">=</span> <span class="n">filename</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>  <span class="k">def</span> <span class="nf">run</span>
</span><span class='line'>    <span class="no">File</span><span class="o">.</span><span class="n">delete</span><span class="p">(</span><span class="vi">@filename</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'><span class="n">context</span> <span class="s2">&quot;when run&quot;</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">let</span><span class="p">(</span><span class="ss">:filename</span><span class="p">){</span><span class="s1">&#39;blah.rb&#39;</span><span class="p">}</span>
</span><span class='line'>  <span class="n">let</span><span class="p">(</span><span class="ss">:sut</span><span class="p">){</span><span class="no">DeleteFileCommand</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">filename</span><span class="p">)}</span>
</span><span class='line'>  <span class="n">before</span> <span class="p">(</span><span class="ss">:each</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">fake_class</span> <span class="no">File</span> <span class="c1"># I usually use multiple before blocks to separate setup from invoking the method I am testing, this could also be in the before block below</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">before</span> <span class="p">(</span><span class="ss">:each</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">sut</span><span class="o">.</span><span class="n">run</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'>
</span><span class='line'>  <span class="n">it</span> <span class="s2">&quot;should delete the file&quot;</span> <span class="k">do</span>
</span><span class='line'>    <span class="no">File</span><span class="o">.</span><span class="n">should</span> <span class="n">have_received</span><span class="p">(</span><span class="ss">:delete</span><span class="p">,</span><span class="n">filename</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>The use of the new fake_class method creates a fake instance (using the existing fake infrastructure) and uses it to be the value used for all class methods on the specified class. You can notice how in the assertion we are verifying that the File class received a call to the delete method with a specified argument. This mechanism is identical to how you can already verify calls made to fakes, with all of the goodness of the <a href="http://blog.developwithpassion.com/2012/06/09/fakes-and-in-turn-fakes-rspec-new-feature-arbitrary-argument-matching-for-setup-and-verification-of-calls/">new arg matching capabilities</a> also available to use.</p>

<p>When you make use of the fake_class method, from that point on any reference to the class that you specified is now talking to the fake. Which means you can also treat it like any other fake when you are setting up fake behaviour. Here is another example:</p>

<figure class='code'><figcaption><span>setting up fake return values -  fake_return_values.rb </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="n">before</span><span class="p">(</span><span class="ss">:each</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">fake_class</span> <span class="no">File</span>
</span><span class='line'>
</span><span class='line'>  <span class="no">File</span><span class="o">.</span><span class="n">stub</span><span class="p">(</span><span class="ss">:exist?</span><span class="p">)</span><span class="o">.</span><span class="n">with</span><span class="p">(</span><span class="n">arg_match</span><span class="o">.</span><span class="n">any</span><span class="p">)</span><span class="o">.</span><span class="n">and_return</span><span class="p">(</span><span class="kp">true</span><span class="p">)</span>
</span><span class='line'><span class="k">end</span>
</span><span class='line'>
</span><span class='line'><span class="n">it</span> <span class="s2">&quot;should never have a file that does not exist&quot;</span> <span class="k">do</span>
</span><span class='line'>  <span class="no">File</span><span class="o">.</span><span class="n">exist?</span><span class="p">(</span><span class="s1">&#39;totally_non_existent_file&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">should</span> <span class="n">be_true</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Hopefully you can see that is a contrived example, but it demonstrates how you can setup behaviours now fully using fakes and not needing to mix and match between fakes and (in my original case, RSpec mocks and stubs).</p>

<p><a href="http://github.com/developwithpassion/fakes-rspec">fakes-rspec</a> has already been rebuilt against this library to take advantage of this feature. The only change that was added to it was literally the following lines of code:</p>

<figure class='code'><figcaption><span>fakes-rspec changes - changes_to_fakes_rspec.rb </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="no">RSpec</span><span class="o">.</span><span class="n">configure</span> <span class="k">do</span> <span class="o">|</span><span class="n">config</span><span class="o">|</span>
</span><span class='line'>  <span class="n">config</span><span class="o">.</span><span class="n">after</span><span class="p">(</span><span class="ss">:each</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">reset_fake_classes</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This just ensures that after each test run, the classes get reset back to their original behaviour. Which means if you are already using fakes-rspec, you can just start using by updating to the latest version!!</p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[fakes (and in turn, fakes-rspec) new feature - Arbitrary argument matching for setup and verification of calls]]></title>
    <link href="http://blog.developwithpassion.com/2012/06/09/fakes-and-in-turn-fakes-rspec-new-feature-arbitrary-argument-matching-for-setup-and-verification-of-calls/"/>
    <updated>2012-06-09T15:27:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/06/09/fakes-and-in-turn-fakes-rspec-new-feature-arbitrary-argument-matching-for-setup-and-verification-of-calls</id>
    <content type="html"><![CDATA[<p>Just added a new feature to <a href="http://github.com/developwithpassion/fakes">fakes</a> to support something I was doing, and it surprised me how I was able to wait until now to add it.  The change did not require any changes to the <a href="http://github.com/developwithpassion/fakes-rspec">fakes-rspec</a> library whatsoever (aside from rebuilding it against the new version of fakes!!</p>

<p>The feature in question is the ability to do arbitrary matching of arguments during both the setup phase for a fake and also for the verification section.</p>

<p>Here is an example of using the capability in your before block to setup a fake to return values for a call:</p>

<figure class='code'><figcaption><span>Setting up a fake to return values when called by using argument matchers - arg_matching_setup.rb </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="n">context</span> <span class="s2">&quot;when setting up a fake using a combination of real values and matchers&quot;</span> <span class="k">do</span>
</span><span class='line'> <span class="n">before</span> <span class="p">(</span><span class="ss">:each</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">fake_item</span><span class="o">.</span><span class="n">stub</span><span class="p">(</span><span class="ss">:do_work</span><span class="p">)</span><span class="o">.</span><span class="n">with</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="n">arg_match</span><span class="o">.</span><span class="n">regex</span><span class="p">(</span><span class="sr">/y/</span><span class="p">)</span><span class="o">.</span><span class="n">and_return</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="n">it</span> <span class="s2">&quot;should be able to return values when calls are made that match the matchers and the real values&quot;</span> <span class="k">do</span>
</span><span class='line'>   <span class="n">fake_item</span><span class="o">.</span><span class="n">do_work</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="s1">&#39;yes&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="mi">3</span>
</span><span class='line'>   <span class="n">fake_item</span><span class="o">.</span><span class="n">do_work</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="s1">&#39;y&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="mi">3</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This is a really basic example, but basically, when you are setting up a method call, you can now specify either the explicit arguments the method should be called with to return a certain value, or you can use argument matchers, or both!! The arg_match method is a gateway to a factory that can create matchers. In pattern terms its a gatway to a specification factory!! You can use one of the prexisting methods:</p>

<ul>
<li>nil</li>
<li>not_nil</li>
<li>any</li>
<li>greater_than</li>
<li>in_range</li>
<li>regex</li>
<li>condition</li>
</ul>


<p>I could add more convienience methods, but they all end up calling into the condition method which just requires a block which matches the signaure:</p>

<figure class='code'><figcaption><span>condition method signature -  condition.rb </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'>  <span class="p">{</span><span class="o">|</span><span class="n">item</span><span class="o">|</span> <span class="n">bool</span><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<p>An example of using this to create an arbitrary matcher is as follows:</p>

<figure class='code'><figcaption><span>Creating an arbitrary matcher- arbitrary_matcher.rb </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="n">context</span> <span class="s2">&quot;when setting up a fake using a combination of real values and matchers&quot;</span> <span class="k">do</span>
</span><span class='line'> <span class="n">let</span><span class="p">(</span><span class="ss">:fake_item</span><span class="p">){</span><span class="n">fake</span><span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="n">before</span> <span class="p">(</span><span class="ss">:each</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">fake_item</span><span class="o">.</span><span class="n">stub</span><span class="p">(</span><span class="ss">:do_work</span><span class="p">)</span><span class="o">.</span><span class="n">with</span><span class="p">(</span><span class="n">arg_match</span><span class="o">.</span><span class="n">condition</span><span class="p">{</span><span class="o">|</span><span class="n">item</span><span class="o">|</span> <span class="o">[</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="o">].</span><span class="n">include?</span><span class="p">(</span><span class="n">item</span><span class="p">)},</span><span class="mi">3</span><span class="p">,</span><span class="n">arg_match</span><span class="o">.</span><span class="n">regex</span><span class="p">(</span><span class="sr">/y)).and_return(3)</span>
</span><span class='line'><span class="sr"> end</span>
</span><span class='line'>
</span><span class='line'><span class="sr"> it &quot;should be able to return values when calls are made that match the matchers and the real values&quot; do</span>
</span><span class='line'><span class="sr">   fake_item.do_work(2,3,&#39;yes&#39;).should == 3</span>
</span><span class='line'><span class="sr">   fake_item.do_work(2,3,&#39;y&#39;).should == 3</span>
</span><span class='line'><span class="sr"> end</span>
</span><span class='line'><span class="sr">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Hopefully you can see that is a contrived example, as we already have the in_range method that can handle that. Of course in place of either of those existing methods, or the condition method, you can just pass in something that responds to: matches?(item). Here is another contrived example:</p>

<figure class='code'><figcaption><span>Passing in your own matcher - custom_matcher.rb </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="n">context</span> <span class="s2">&quot;when setting up a fake using a combination of real values and matchers&quot;</span> <span class="k">do</span>
</span><span class='line'> <span class="n">let</span><span class="p">(</span><span class="ss">:fake_item</span><span class="p">){</span><span class="n">fake</span><span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="k">class</span> <span class="nc">CustomArgMatching</span>
</span><span class='line'>   <span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">matches?</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
</span><span class='line'>    <span class="n">item</span>  <span class="o">!=</span> <span class="mi">42</span>
</span><span class='line'>   <span class="k">end</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="n">before</span> <span class="p">(</span><span class="ss">:each</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">fake_item</span><span class="o">.</span><span class="n">stub</span><span class="p">(</span><span class="ss">:do_work</span><span class="p">)</span><span class="o">.</span><span class="n">with</span><span class="p">(</span><span class="no">CustomArgMatching</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="n">arg_match</span><span class="o">.</span><span class="n">regex</span><span class="p">(</span><span class="sr">/y/</span><span class="p">))</span><span class="o">.</span><span class="n">and_return</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="n">it</span> <span class="s2">&quot;should be able to return values when calls are made that match the matchers and the real values&quot;</span> <span class="k">do</span>
</span><span class='line'>   <span class="n">fake_item</span><span class="o">.</span><span class="n">do_work</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="s1">&#39;yes&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="mi">3</span>
</span><span class='line'>   <span class="n">fake_item</span><span class="o">.</span><span class="n">do_work</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="s1">&#39;y&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="mi">3</span>
</span><span class='line'>   <span class="n">fake_item</span><span class="o">.</span><span class="n">do_work</span><span class="p">(</span><span class="mi">42</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="s1">&#39;y&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">should</span> <span class="o">==</span> <span class="kp">nil</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>This same mechanism works identically when you are doing post invocation verification. Here is another example:</p>

<figure class='code'><figcaption><span>Post invocation verification - post_invocation_verification.rb </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='rb'><span class='line'><span class="n">context</span> <span class="s2">&quot;when verifying that calls are made, using argument matchers&quot;</span> <span class="k">do</span>
</span><span class='line'> <span class="n">let</span><span class="p">(</span><span class="ss">:fake_item</span><span class="p">){</span><span class="n">fake</span><span class="p">}</span>
</span><span class='line'>
</span><span class='line'> <span class="n">before</span> <span class="p">(</span><span class="ss">:each</span><span class="p">)</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">fake_item</span><span class="o">.</span><span class="n">do_work</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="s1">&#39;yes&#39;</span><span class="p">)</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'>
</span><span class='line'> <span class="n">it</span> <span class="s2">&quot;should be able to make call verifications&quot;</span> <span class="k">do</span>
</span><span class='line'>   <span class="n">fake_item</span><span class="o">.</span><span class="n">should</span> <span class="n">have_received</span><span class="p">(</span><span class="ss">:do_work</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="s1">&#39;yes&#39;</span><span class="p">)</span> <span class="c1"># this is doing fully explicit matching on each argument</span>
</span><span class='line'>   <span class="n">fake_item</span><span class="o">.</span><span class="n">should</span> <span class="n">have_received</span><span class="p">(</span><span class="ss">:do_work</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="n">arg_match</span><span class="o">.</span><span class="n">regex</span><span class="p">(</span><span class="sr">/y/</span><span class="p">))</span> <span class="c1"># this is matching explicitly on the first 2 arguments and using a matcher on the last</span>
</span><span class='line'>   <span class="n">fake_item</span><span class="o">.</span><span class="n">should</span> <span class="n">have_received</span><span class="p">(</span><span class="ss">:do_work</span><span class="p">,</span><span class="n">arg_match</span><span class="o">.</span><span class="n">any</span><span class="p">,</span><span class="n">arg_match</span><span class="o">.</span><span class="n">any</span><span class="p">,</span><span class="n">arg_match</span><span class="o">.</span><span class="n">regex</span><span class="p">(</span><span class="sr">/y/</span><span class="p">))</span> <span class="c1"># this is matching using matchers for all 3 (even though the first 2 matchers are just a special case)</span>
</span><span class='line'> <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>Whether you are in the setup phase or the verification phase the model is consistent. You can mix and match the matchers in place of real arguments as you need to. This ultimately gives you much better control on focusing on what it is you care about in the particular interaction you are observing!!</p>

<p>Hopefully you will find this as useful as I do!!</p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Screencast - Creating Linked Clones With VMWare Fusion]]></title>
    <link href="http://blog.developwithpassion.com/2012/04/17/screencast-creating-linked-clones-with-vmware-fusion/"/>
    <updated>2012-04-17T09:27:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/04/17/screencast-creating-linked-clones-with-vmware-fusion</id>
    <content type="html"><![CDATA[<p>This is a short 11 minute video that walks you through the process of creating linked clones using VMWare Fusion.</p>

<p>VMWare Fusion fully supports linked clones;unlike VMWare Workstation it does not yet have a UI to create and manage them.</p>

<p>This video covers the main points:</p>

<ul>
<li>How I organize and separate my vms from the vmdks.</li>
<li>Creating linked clones</li>
</ul>


<p><strong>Shamless Plug</strong> - Aside from the first click, no other mouse usage occured during the course of this video, courtesy of <a href="http://keymando.com">keymando</a>.</p>

<iframe src="http://player.vimeo.com/video/40497134 " width='400' height='255' frameborder='0' webKitAllowFullScreen mozillallowfullscreen allowFullScreen></iframe>


<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Fixing header file missing warnings on OSX with native gem compilation]]></title>
    <link href="http://blog.developwithpassion.com/2012/04/13/fixing-header-file-missing-warnings-on-osx-with-native-gem-compilation/"/>
    <updated>2012-04-13T18:29:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/04/13/fixing-header-file-missing-warnings-on-osx-with-native-gem-compilation</id>
    <content type="html"><![CDATA[<p>Wiped away my install of XCode this evening to install the new version of Xcode (which I installed straight to /Applications!).</p>

<p>Prior to doing this I also completely deleted the /Developer folder.</p>

<p>Upon successfully reinstalling <a href="http://beginrescueend.com">RVM</a> and <a href="https://github.com/mxcl/homebrew">homebrew</a> using the <a href="http://github.com/developwithpassion/devtools">devtools</a>, I cd&#8217;d into a rvm managed folder and did the standard bundle install, upon which time I eventually received this error:</p>

<figure class='code'><figcaption><span>Error - error.sh  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>: fatal error: <span class="s1">&#39;stdio.h&#39;</span> file not found
</span></code></pre></td></tr></table></div></figure>


<p>I had installed the Command Line Tools for Xcode, but I had not yet switched where it should resolve those tools. Running the following command fixed the issue:</p>

<figure class='code'><figcaption><span>Fix the missing header issue - fix.sh  </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>sudo xcode-select -switch /Applications/Xcode.app/Contents/Developer
</span></code></pre></td></tr></table></div></figure>


<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Installing RVM with Cygwin On Windows]]></title>
    <link href="http://blog.developwithpassion.com/2012/03/30/installing-rvm-with-cygwin-on-windows/"/>
    <updated>2012-03-30T18:19:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/03/30/installing-rvm-with-cygwin-on-windows</id>
    <content type="html"><![CDATA[<p>A couple of people have asked me how to get rvm working successfully on windows with cygwin.</p>

<p>I&#8217;ll write another post later about how I use <a href="http://github.com/developwithpassion/devtools">devtools</a> to successfully run msys and cygwin side by side from the same set of dotfiles (customized per environment)!</p>

<p>I started with a brand new vm image with the software installed according to the post <a href="http://blog.developwithpassion.com/2012/03/12/repaving-a-new-window-7-vm/">here</a>.</p>

<p>If you don&#8217;t wish to read that previous post just know I installed cygwin to C:\utils\cygwin (for the purpose of this post it you are following along, I would suggest installing to that path also). I also included the following packages (some of these are not necessary for ruby compilation, but they have become my base for a cygwin install):</p>

<ul>
<li>Archive

<ul>
<li>unzip - Unzipping zip files</li>
</ul>
</li>
<li>Net

<ul>
<li>openssl - bin and sources</li>
<li>openssh - Only if you are not going to compile openssh yourself</li>
<li>curl - download internet resources</li>
</ul>
</li>
<li>Devl

<ul>
<li>colorgcc</li>
<li>gcc</li>
<li>gcc-core - compiler</li>
<li>git</li>
<li>git-completion</li>
<li>git-gui</li>
<li>git-svn</li>
<li>gitk</li>
<li>libtool - Shared library generation tool. You&#8217;ll need it when trying to compile rubies</li>
<li>libncurses-devel - Used when compiling several other tools I use</li>
<li>make</li>
<li>mercurial</li>
<li>openssl-devel - Required for compiling openssh (not necessarily required for rvm, but I always install it to compile openssh myself)</li>
<li>readline</li>
</ul>
</li>
<li>Libs

<ul>
<li>zlib</li>
<li>zlib-devel</li>
</ul>
</li>
<li>Utils

<ul>
<li>ncurses - Enabling better handling of terminal</li>
<li>patch - Apply a diff file to an original. Again, you&#8217;ll need it when rvm is trying to patch the ruby installs</li>
</ul>
</li>
</ul>


<p>Once the cygwin install completes we can continue.</p>

<h2>Setting Up</h2>

<ul>
<li><p>Open up a new cygwin session (C:\utils\cygwin\cygwin.bat).</p></li>
<li><p>Issue the following commands in the cygwin session:</p></li>
</ul>


<figure class='code'><figcaption><span>Get The devtools - devtools.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>mkdir repositories
</span><span class='line'><span class="nb">cd </span>repositories
</span><span class='line'>mkdir developwithpassion
</span><span class='line'><span class="nb">cd </span>developwithpassion
</span><span class='line'>git clone git://github.com/developwithpassion/devtools
</span><span class='line'><span class="nb">cd </span>devtools
</span></code></pre></td></tr></table></div></figure>


<p>  The results should look as follows:</p>

<p><img class="centered" src="https://img.skitch.com/20120415-8sw3uup1pamxd4gbr934s3hshd.jpg"></p>

<ul>
<li>You should now be sitting in the devtools folder so you can now run the kick_off_script:</li>
</ul>


<figure class='code'><figcaption><span>Prep - kick_off.sh </span></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='sh'><span class='line'>./osx_or_cygwin_kick_off
</span></code></pre></td></tr></table></div></figure>


<ul>
<li><p>Repeat the above step(the first time you run it, it creates a settings file for your user that can be edited further if you are going to make further use of <a href="http://github.com/developwithpassion/devtools">devtools</a> later on)</p>

<p>For the curious, the script is <a href="https://raw.github.com/developwithpassion/devtools/master/osx_or_cygwin_kick_off">here</a></p>

<p>The script does the following:</p>

<ul>
<li>kicks off an rvm installation script</li>
<li>updates to the latest rvm</li>
<li>installs a couple of rubies and sets 1.9.3 as the default ruby</li>
</ul>
</li>
</ul>


<p>The last step takes a little time to complete, but the end result is definitely worth it!!:</p>

<p><img class="centered" src="https://img.skitch.com/20120331-1ix7mmijphenimhb4jui3cic45.jpg"></p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Webinar - devtools - An walkthrough of my devtools setup]]></title>
    <link href="http://blog.developwithpassion.com/2012/03/28/webinar-devtools-an-walkthrough-of-my-devtools-setup/"/>
    <updated>2012-03-28T09:19:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/03/28/webinar-devtools-an-walkthrough-of-my-devtools-setup</id>
    <content type="html"><![CDATA[<p>Today I will be hosting a 1 hour webinar showing you how to get started with my <a href="https://github.com/developwithpassion/devtools">devtools</a> utilities.</p>

<p>Here is the information for the webinar:</p>

<p><a href="https://www1.gotomeeting.com/register/493822104">Reserve your Webinar seat now at:</a></p>

<p>This webinar will be an opportunity for people to get an understanding of how I structure my devtools folder and how it is leveraged to facilitate working effectively between osx and windows.</p>

<p>Title:  Develop With Passion® - devtools
Date:   Wednesday, March 28, 2012
Time:   12:00 PM - 1:00 PM MDT</p>

<p>After registering you will receive a confirmation email containing information about joining the Webinar.</p>

<p>System Requirements
* PC-based attendees
* Required: Windows® 7, Vista, XP or 2003 Server
* Macintosh®-based attendees
* Required: Mac OS® X 10.5 or newer</p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[April Brussels Course: Rescheduled]]></title>
    <link href="http://blog.developwithpassion.com/2012/03/28/april-brussels-course-postponed/"/>
    <updated>2012-03-28T04:52:00-06:00</updated>
    <id>http://blog.developwithpassion.com/2012/03/28/april-brussels-course-postponed</id>
    <content type="html"><![CDATA[<p>I am sorry to announce that next month&#8217;s .Net Software Craftmanship BootCamp in Brussels, has been rescheduled until the week of September 17th.</p>

<p>Being our first time in Brussels, we are hoping that pushing back the date will provide more people with an opportunity to convince their bosses that the course is a good investment!</p>

<p>I apologize for any inconvienience this may cause.</p>

<p>God Bless You.</p>

<p><a href="http://www.developwithpassion.com">Develop With Passion®</a></p>
]]></content>
  </entry>
  
</feed>
