<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
     xmlns:content="http://purl.org/rss/1.0/modules/content/"
     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
     xmlns:atom="http://www.w3.org/2005/Atom"
     xmlns:dc="http://purl.org/dc/elements/1.1/"
     xmlns:wfw="http://wellformedweb.org/CommentAPI/"
     >
  <channel>
    <title>EnigmaCurry</title>
    <link>http://www.enigmacurry.com/</link>
    <description>The Curry Enigma</description>
    <pubDate>Mon, 02 Aug 2010 17:43:01 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Audacious Dynamic Playlist powered by inotify</title>
      <link>http://www.enigmacurry.com/2010/07/13/audacious-dynamic-playlist-powered-by-inotify</link>
      <pubDate>Tue, 13 Jul 2010 00:22:00 EDT</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Linux]]></category>
      <guid isPermaLink="true">http://www.enigmacurry.com/2010/07/13/audacious-dynamic-playlist-powered-by-inotify</guid>
      <description>Audacious Dynamic Playlist powered by inotify</description>
      <content:encoded><![CDATA[<p>I was playing around with <a href="http://streamripper.sourceforge.net/">StreamRipper</a> today to record a shoutcast stream I enjoy, and I thought to myself: wouldn't it be nice to be able to continuously play all the files I've downloaded without having to manually queue the new files in <a href="http://audacious-media-player.org/">Audacious</a>?
</p>
<p>So, I scratched an itch. With a little DBUS, pyinotify, and an optparse wrapper, I now have a tool to automatically add the tracks to my Audacious playlist. You can grab the <a href="http://github.com/EnigmaCurry/audacious-plugins">latest version on github</a>.
</p>
<p>Streamripper does have a relay option (-r) to allow you to listen to the same stream as you're ripping it, and if that's what you want, the following script is superfluous. However, what I wanted was something slightly different: I didn't necessarily want to just listen to the stream live, instead, I wanted the ability to jump around between the tracks already downloaded, exploring different songs, but with the list of tracks ever expanding. That's what this script allows.
</p>
<p>You'll need python-dbus and setuptools installed, then just install with:
</p>
<div class="pygments_murphy"><pre>easy_install http://github.com/EnigmaCurry/audacious-plugins/zipball/master
</pre></div>

<p>Startup <a href="http://streamripper.sourceforge.net/">StreamRipper</a> with your favorite audio stream and point the tool at your target directory:
</p>
<div class="pygments_murphy"><pre>python -m ec_audacious.dynamic_filesystem_playlist /path/to/your/streamripper_location
</pre></div>

<p>Now when StreamRipper creates a new file, it will get automatically (instantaeneously actually, thanks to inotify!) to your Audacious playlist.
</p>
<p>Alternatively, you can use the streamripper wrapper script that I've included to start both the filesystem monitor as well as streamripper in one go:
</p>
<p>Put the following in your .bashrc file or somewhere equivalent:
</p>
<div class="pygments_murphy"><pre><span class="nb">alias </span><span class="nv">streamripper</span><span class="o">=</span><span class="s2">&quot;python -m ec_audacious.streamripper&quot;</span>
</pre></div>

<p>Then whenever you run streamripper, you'll actually be running the wrapper script instead:
</p>
<div class="pygments_murphy"><pre>streamripper http://your-cool-stream.com:8000 --audacious
</pre></div>

<p>By aliasing streamripper to point to the ec_audacious.streamripper wrapper script, we're effectively adding a new option to streamripper called --audacious which spawns our filesystem monitor.
</p>]]></content:encoded>
    </item>
    <item>
      <title>AutoComplete.el : Python Code Completion in Emacs</title>
      <link>http://www.enigmacurry.com/2009/01/21/autocompleteel-python-code-completion-in-emacs/</link>
      <pubDate>Wed, 21 Jan 2009 22:01:10 EST</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Emacs]]></category>
      <category><![CDATA[Linux]]></category>
      <guid>http://www.enigmacurry.com/?p=401</guid>
      <description>AutoComplete.el : Python Code Completion in Emacs</description>
      <content:encoded><![CDATA[
<center><img src="/blog-post-images/PythonCodeCompletion_Rope_Autocomplete.png" /></center>

<p>A <a href="http://www.travishartwell.net/blog">friend of mine</a> and I like to show off to each other little Emacs tips and tricks we learn. Today, he introduced to me the very cool <a href="http://www.emacswiki.org/emacs/AutoComplete">AutoComplete.el package</a>.  AutoComplete.el is intriguing to me because, unlike ropemacs mode <a href="/2008/05/09/emacs-as-a-powerful-python-ide/">which I've blogged about before</a>, the completions AutoComplete.el provides are inline with your code in a dropdown box instead of in a seperate window (windows in Emacs are what most people call frames). However, AutoComplete is only a completion framework, it doesn't know anything about Python. Instead, it allows the user to plug into it, feeding it whatever sorts of intelligent completion you want, including <a href="http://rope.sourceforge.net">Rope</a>.</p>

<h2 class="intrablog">Setup</h2>

<p>The two most important completions I want to integrate into it are <a href="http://rope.sourceforge.net">Rope</a> and <a href="http://code.google.com/p/yasnippet/">yasnippet.</a> AutoComplete can handle both of them nicely. You'll need to install the <b><em>very latest development version</em></b> (as of December '08) of Rope, Ropemacs and Ropemode:</p>


<div class="pygments_murphy"><pre>sudo apt-get install mercurial
mkdir /tmp/rope <span class="o">&amp;&amp;</span> <span class="nb">cd</span> /tmp/rope
hg clone http://bitbucket.org/agr/rope
hg clone http://bitbucket.org/agr/ropemacs
hg clone http://bitbucket.org/agr/ropemode
sudo easy_install rope
ln -s ../ropemode/ropemode ropemacs/
sudo easy_install ropemacs
</pre></div>




<p>You'll also need to install <a href="http://pymacs.progiciels-bpi.ca/">Pymacs</a>  and <a href="http://code.google.com/p/yasnippet">Yasnippet</a> if you haven't already: </p>


<div class="pygments_murphy"><pre>mkdir -p ~/.emacs.d/vendor <span class="o">&amp;&amp;</span> <span class="nb">cd</span> ~/.emacs.d/vendor
wget http://pymacs.progiciels-bpi.ca/archives/Pymacs-0.23.tar.gz
tar xfv Pymacs-0.23.tar.gz
<span class="nb">cd </span>Pymacs-0.23
make
sudo easy_install .
<span class="nb">cd</span> ~/.emacs.d/vendor
wget http://yasnippet.googlecode.com/files/yasnippet-0.5.9.tar.bz2
tar xfv yasnippet-0.5.9.tar.bz2
<span class="nb">cd</span> ~/.emacs.d
ln -s vendor/yasnippet-0.5.9/snippets/ .
</pre></div>




<p>Make sure Pymacs and Yasnippet get into your load path, in your .emacs:</p>

<div class="pygments_murphy"><pre><span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;load-path</span> <span class="s">&quot;~/.emacs.d/vendor&quot;</span><span class="p">)</span>
<span class="p">(</span><span class="k">progn</span> <span class="p">(</span><span class="nv">cd</span> <span class="s">&quot;~/.emacs.d/vendor&quot;</span><span class="p">)</span>
       <span class="p">(</span><span class="nv">normal-top-level-add-subdirs-to-load-path</span><span class="p">))</span>
</pre></div>




<p>Install AutoComplete.el 0.1.0 (0.2.0 is now out, and is not compatible with this post, I'll try and update later):</p>


<div class="pygments_murphy"><pre><span class="nb">cd</span> ~/.emacs.d/vendor
wget http://www.emacswiki.org/emacs/?action<span class="o">=</span>browse;id<span class="o">=</span>auto-complete.el;raw<span class="o">=</span>1;revision<span class="o">=</span>5
</pre></div>




<p>Now to add some more elisp to your .emacs somewhere:</p>


<div class="pygments_murphy"><pre><span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;python</span><span class="p">)</span>
<span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;auto-complete</span><span class="p">)</span>
<span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;yasnippet</span><span class="p">)</span>

<span class="p">(</span><span class="nv">autoload</span> <span class="ss">&#39;python-mode</span> <span class="s">&quot;python-mode&quot;</span> <span class="s">&quot;Python Mode.&quot;</span> <span class="no">t</span><span class="p">)</span>
<span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;auto-mode-alist</span> <span class="o">&#39;</span><span class="p">(</span><span class="s">&quot;\\.py\\&#39;&quot;</span> <span class="o">.</span> <span class="nv">python-mode</span><span class="p">))</span>
<span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;interpreter-mode-alist</span> <span class="o">&#39;</span><span class="p">(</span><span class="s">&quot;python&quot;</span> <span class="o">.</span> <span class="nv">python-mode</span><span class="p">))</span>

<span class="c1">;; Initialize Pymacs                                                                                           </span>
<span class="p">(</span><span class="nv">autoload</span> <span class="ss">&#39;pymacs-apply</span> <span class="s">&quot;pymacs&quot;</span><span class="p">)</span>
<span class="p">(</span><span class="nv">autoload</span> <span class="ss">&#39;pymacs-call</span> <span class="s">&quot;pymacs&quot;</span><span class="p">)</span>
<span class="p">(</span><span class="nv">autoload</span> <span class="ss">&#39;pymacs-eval</span> <span class="s">&quot;pymacs&quot;</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)</span>
<span class="p">(</span><span class="nv">autoload</span> <span class="ss">&#39;pymacs-exec</span> <span class="s">&quot;pymacs&quot;</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)</span>
<span class="p">(</span><span class="nv">autoload</span> <span class="ss">&#39;pymacs-load</span> <span class="s">&quot;pymacs&quot;</span> <span class="no">nil</span> <span class="no">t</span><span class="p">)</span>
<span class="c1">;; Initialize Rope                                                                                             </span>
<span class="p">(</span><span class="nv">pymacs-load</span> <span class="s">&quot;ropemacs&quot;</span> <span class="s">&quot;rope-&quot;</span><span class="p">)</span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">ropemacs-enable-autoimport</span> <span class="no">t</span><span class="p">)</span>

<span class="c1">;; Initialize Yasnippet                                                                                        </span>
<span class="c1">;Don&#39;t map TAB to yasnippet                                                                                    </span>
<span class="c1">;In fact, set it to something we&#39;ll never use because                                                          </span>
<span class="c1">;we&#39;ll only ever trigger it indirectly.                                                                        </span>
<span class="p">(</span><span class="k">setq</span> <span class="nv">yas/trigger-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">&quot;C-c &lt;kp-multiply&gt;&quot;</span><span class="p">))</span>
<span class="p">(</span><span class="nv">yas/initialize</span><span class="p">)</span>
<span class="p">(</span><span class="nv">yas/load-directory</span> <span class="s">&quot;~/.emacs.d/snippets&quot;</span><span class="p">)</span>



<span class="c1">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                                         </span>
<span class="c1">;;; Auto-completion                                                                                            </span>
<span class="c1">;;;  Integrates:                                                                                               </span>
<span class="c1">;;;   1) Rope                                                                                                  </span>
<span class="c1">;;;   2) Yasnippet                                                                                             </span>
<span class="c1">;;;   all with AutoComplete.el                                                                                 </span>
<span class="c1">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                                         </span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">prefix-list-elements</span> <span class="p">(</span><span class="nb">list</span> <span class="nv">prefix</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">(</span><span class="nv">value</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">nreverse</span>
     <span class="p">(</span><span class="nb">dolist</span> <span class="p">(</span><span class="nv">element</span> <span class="nb">list</span> <span class="nv">value</span><span class="p">)</span>
      <span class="p">(</span><span class="k">setq</span> <span class="nv">value</span> <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;%s%s&quot;</span> <span class="nv">prefix</span> <span class="nv">element</span><span class="p">)</span> <span class="nv">value</span><span class="p">))))))</span>
<span class="p">(</span><span class="nb">defvar</span> <span class="nv">ac-source-rope</span>
  <span class="o">&#39;</span><span class="p">((</span><span class="nv">candidates</span>
     <span class="o">.</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">()</span>
         <span class="p">(</span><span class="nv">prefix-list-elements</span> <span class="p">(</span><span class="nv">rope-completions</span><span class="p">)</span> <span class="nv">ac-target</span><span class="p">))))</span>
  <span class="s">&quot;Source for Rope&quot;</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">ac-python-find</span> <span class="p">()</span>
  <span class="s">&quot;Python `ac-find-function&#39;.&quot;</span>
  <span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;thingatpt</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nc">symbol</span> <span class="p">(</span><span class="nv">car-safe</span> <span class="p">(</span><span class="nv">bounds-of-thing-at-point</span> <span class="ss">&#39;symbol</span><span class="p">))))</span>
    <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">null</span> <span class="nc">symbol</span><span class="p">)</span>
        <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">string=</span> <span class="s">&quot;.&quot;</span> <span class="p">(</span><span class="nv">buffer-substring</span> <span class="p">(</span><span class="nb">-</span> <span class="p">(</span><span class="nv">point</span><span class="p">)</span> <span class="mi">1</span><span class="p">)</span> <span class="p">(</span><span class="nv">point</span><span class="p">)))</span>
            <span class="p">(</span><span class="nv">point</span><span class="p">)</span>
          <span class="no">nil</span><span class="p">)</span>
      <span class="nc">symbol</span><span class="p">)))</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">ac-python-candidate</span> <span class="p">()</span>
  <span class="s">&quot;Python `ac-candidates-function&#39;&quot;</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">(</span><span class="nv">candidates</span><span class="p">)</span>
    <span class="p">(</span><span class="nb">dolist</span> <span class="p">(</span><span class="nv">source</span> <span class="nv">ac-sources</span><span class="p">)</span>
      <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">symbolp</span> <span class="nv">source</span><span class="p">)</span>
          <span class="p">(</span><span class="k">setq</span> <span class="nv">source</span> <span class="p">(</span><span class="nb">symbol-value</span> <span class="nv">source</span><span class="p">)))</span>
      <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">ac-limit</span> <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nv">cdr-safe</span> <span class="p">(</span><span class="nv">assq</span> <span class="ss">&#39;limit</span> <span class="nv">source</span><span class="p">))</span> <span class="nv">ac-limit</span><span class="p">))</span>
             <span class="p">(</span><span class="nv">requires</span> <span class="p">(</span><span class="nv">cdr-safe</span> <span class="p">(</span><span class="nv">assq</span> <span class="ss">&#39;requires</span> <span class="nv">source</span><span class="p">)))</span>
             <span class="nv">cand</span><span class="p">)</span>
        <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">or</span> <span class="p">(</span><span class="nb">null</span> <span class="nv">requires</span><span class="p">)</span>
                <span class="p">(</span><span class="nb">&gt;=</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">ac-target</span><span class="p">)</span> <span class="nv">requires</span><span class="p">))</span>
            <span class="p">(</span><span class="k">setq</span> <span class="nv">cand</span>
                  <span class="p">(</span><span class="nv">delq</span> <span class="no">nil</span>
                        <span class="p">(</span><span class="nb">mapcar</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">(</span><span class="nv">candidate</span><span class="p">)</span>
                                  <span class="p">(</span><span class="nv">propertize</span> <span class="nv">candidate</span> <span class="ss">&#39;source</span> <span class="nv">source</span><span class="p">))</span>
                                <span class="p">(</span><span class="nb">funcall</span> <span class="p">(</span><span class="nb">cdr</span> <span class="p">(</span><span class="nv">assq</span> <span class="ss">&#39;candidates</span> <span class="nv">source</span><span class="p">)))))))</span>
        <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">&gt;</span> <span class="nv">ac-limit</span> <span class="mi">1</span><span class="p">)</span>
                 <span class="p">(</span><span class="nb">&gt;</span> <span class="p">(</span><span class="nb">length</span> <span class="nv">cand</span><span class="p">)</span> <span class="nv">ac-limit</span><span class="p">))</span>
            <span class="p">(</span><span class="nv">setcdr</span> <span class="p">(</span><span class="nb">nthcdr</span> <span class="p">(</span><span class="nb">1-</span> <span class="nv">ac-limit</span><span class="p">)</span> <span class="nv">cand</span><span class="p">)</span> <span class="no">nil</span><span class="p">))</span>
        <span class="p">(</span><span class="k">setq</span> <span class="nv">candidates</span> <span class="p">(</span><span class="nb">append</span> <span class="nv">candidates</span> <span class="nv">cand</span><span class="p">))))</span>
    <span class="p">(</span><span class="nv">delete-dups</span> <span class="nv">candidates</span><span class="p">)))</span>
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;python-mode-hook</span>
          <span class="p">(</span><span class="k">lambda</span> <span class="p">()</span>
                 <span class="p">(</span><span class="nv">auto-complete-mode</span> <span class="mi">1</span><span class="p">)</span>
                 <span class="p">(</span><span class="nb">set</span> <span class="p">(</span><span class="nv">make-local-variable</span> <span class="ss">&#39;ac-sources</span><span class="p">)</span>
                      <span class="p">(</span><span class="nb">append</span> <span class="nv">ac-sources</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">ac-source-rope</span><span class="p">)</span> <span class="o">&#39;</span><span class="p">(</span><span class="nv">ac-source-yasnippet</span><span class="p">)))</span>
                 <span class="p">(</span><span class="nb">set</span> <span class="p">(</span><span class="nv">make-local-variable</span> <span class="ss">&#39;ac-find-function</span><span class="p">)</span> <span class="ss">&#39;ac-python-find</span><span class="p">)</span>
                 <span class="p">(</span><span class="nb">set</span> <span class="p">(</span><span class="nv">make-local-variable</span> <span class="ss">&#39;ac-candidate-function</span><span class="p">)</span> <span class="ss">&#39;ac-python-candidate</span><span class="p">)</span>
                 <span class="p">(</span><span class="nb">set</span> <span class="p">(</span><span class="nv">make-local-variable</span> <span class="ss">&#39;ac-auto-start</span><span class="p">)</span> <span class="no">nil</span><span class="p">)))</span>

<span class="c1">;;Ryan&#39;s python specific tab completion                                                                        </span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">ryan-python-tab</span> <span class="p">()</span>
  <span class="c1">; Try the following:                                                                                         </span>
  <span class="c1">; 1) Do a yasnippet expansion                                                                                </span>
  <span class="c1">; 2) Do a Rope code completion                                                                               </span>
  <span class="c1">; 3) Do an indent                                                                                            </span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">eql</span> <span class="p">(</span><span class="nv">ac-start</span><span class="p">)</span> <span class="mi">0</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">indent-for-tab-command</span><span class="p">)))</span>

<span class="p">(</span><span class="nv">defadvice</span> <span class="nv">ac-start</span> <span class="p">(</span><span class="nv">before</span> <span class="nv">advice-turn-on-auto-start</span> <span class="nv">activate</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">set</span> <span class="p">(</span><span class="nv">make-local-variable</span> <span class="ss">&#39;ac-auto-start</span><span class="p">)</span> <span class="no">t</span><span class="p">))</span>
<span class="p">(</span><span class="nv">defadvice</span> <span class="nv">ac-cleanup</span> <span class="p">(</span><span class="nv">after</span> <span class="nv">advice-turn-off-auto-start</span> <span class="nv">activate</span><span class="p">)</span>
  <span class="p">(</span><span class="nb">set</span> <span class="p">(</span><span class="nv">make-local-variable</span> <span class="ss">&#39;ac-auto-start</span><span class="p">)</span> <span class="no">nil</span><span class="p">))</span>

<span class="p">(</span><span class="nv">define-key</span> <span class="nv">python-mode-map</span> <span class="s">&quot;\t&quot;</span> <span class="ss">&#39;ryan-python-tab</span><span class="p">)</span>
<span class="c1">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;                                         </span>
<span class="c1">;;; End Auto Completion                                                                                        </span>
<span class="c1">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</span>
</pre></div>




<h2 class="intrablog">Github</h2>

<p>These changes are also applied to my <a href="http://www.github.com/EnigmaCurry/emacs">Emacs environment on Github.</a> I'm continuously trying to improve my emacs setup, so if you're reading this a few months/years after this post was made, you may want to check there for improvements.</p>

<p><b>Update Jan 30 2009:</b> I made some modifications to the tab complete order, a regular indent is applied first before autocompletion. Autocompletion is also not applied unless you are at the end of a word. This is useful when you press Tab at the beginning of a line to indent/outdent.</p>

<h2 class="intrablog">Usage</h2>
<p>Once you got everything setup, usage is real easy:</p>
<ol>
<li>Open up a python (.py) file</li>
<li>Press TAB when you want to use code completion or to insert a snippet.</li>
</ol>

<p>The first time you attempt to use code completion you'll be prompted to enter the root of your project directory.</p>

<h2 class="intrablog">Future</h2>
<p>It wasn't too long ago when Python code completion inside Emacs was just a pipedream. So now that we have it, let's make some more pipedreams: I'd like to popup some nice contextual help for method arguments as well as python documentation for the current method/class being completed. </p>

<p>The possibilities are pretty much endless. I love Emacs.</p>
]]></content:encoded>
    </item>
    <item>
      <title>256 colors on the Linux terminal</title>
      <link>http://www.enigmacurry.com/2009/01/20/256-colors-on-the-linux-terminal/</link>
      <pubDate>Tue, 20 Jan 2009 12:30:43 EST</pubDate>
      <category><![CDATA[Emacs]]></category>
      <category><![CDATA[Linux]]></category>
      <guid>http://www.enigmacurry.com/?p=394</guid>
      <description>256 colors on the Linux terminal</description>
      <content:encoded><![CDATA[
<p>I've been using Linux as my main OS for well over a decade now. I can hardly believe I didn't pick up on this tip before.</p>

<p>On your linux desktop, open up your favorite terminal emulator. Enter this command:</p>


<div class="pygments_murphy"><pre>tput colors
</pre></div>




<p>What number do you see? 8?</p>

<p>8 stinking colors. That's what my terminal is capable of displaying. It's 2009 folks, and my terminal can only display <strong>8 stinking colors.</strong></p>

<p>Load up emacs in the terminal (emacs -nw) and see for yourselves, M-x list-colors-display shows you all of the different colors your terminal can display.</p>

<img src="/blog-post-images/Emacs-8-colors.png" />

<p>Pitiful.</p>

<p>Ok, so how to improve this? On ubuntu:</p>


<div class="pygments_murphy"><pre>sudo apt-get install ncurses-term
</pre></div>




<p>and stick the following in your ~/.bashrc and/or ~/.bash_profile:</p>


<div class="pygments_murphy"><pre><span class="nb">export </span><span class="nv">TERM</span><span class="o">=</span>xterm-256color
</pre></div>




<img src="/blog-post-images/Emacs-256-colors.png" />

<p>Ahhhhh...</p>
]]></content:encoded>
    </item>
    <item>
      <title>Ubuntu: coping with a height restricted display</title>
      <link>http://www.enigmacurry.com/2008/12/10/ubuntu-coping-with-a-height-restricted-display/</link>
      <pubDate>Wed, 10 Dec 2008 13:06:48 EST</pubDate>
      <category><![CDATA[Linux]]></category>
      <guid>http://www.enigmacurry.com/?p=250</guid>
      <description>Ubuntu: coping with a height restricted display</description>
      <content:encoded><![CDATA[
<p>I'm eagerly awaiting my new Samsung NC10 to be shipped from Amazon. It's a nice little netbook that I can use when traveling and when going to <a href="http://nhunderground.com/forum/index.php?topic=11326.0">social occasions</a>. I'm specifically buying this laptop because of its small size, but I know that one thing specifically will bother me: the screen resolution, at 1024x600 is wide enough for most tasks, but not very tall at all.</p>

<p>So while I'm waiting, I'm playing around with Ubuntu 8.10 inside a VirtualBox instance. I've got the window resized to 1024x600 and am playing around with different settings to make maximum use of the screen. Here are my tweaks:</p>

<h3>Gnome Panel (the toolbar):</h3>
<p>Open gconf-editor (Alt-F2 'gconf-editor') and navigate to <b>apps -> panel -> toplevels -> top_panel_screen0</b> and change the following:</p>
          <ul>
            <li>auto_hide: checked  -- makes the main toolbar panel autohide</li>
	    <li>auto_hide_size: 0 -- makes the toolbar completely hide instead of leaving a few pixels visible</li>
            <li>enable_animations: unchecked  -- make the hiding/unhiding as fast as possible</li>
            <li>hide_delay: 500 -- makes the toolbar stay on screen for half a second after using it</li>
            <li>unhide_delay: 0 -- makes the toolbar immediately popup when your mouse goes to the very top (or bottom) of the screen</li>
 <a href="/blog-post-images/hr_gconf-panel-prefs.png"><img src="/blog-post-images/hr_gconf-panel-prefs.png" alt="" title="hr_gconf-panel-prefs" width="500" class="alignnone size-medium wp-image-252" /></a>
          </ul>

<h3>Gnome Terminal:</h3>
<p> Open the default profile properties, right click in the window and click "Edit Current Profile"</p>
<ul>
	<li>Turn off the menu bar: on the General tab uncheck "Show menubar by default in new terminals"</li>
	<li>Turn off the scrollbar: on the Scrolling tab select "Scrollbar is: Disabled"</li>
</ul>

<h3>Oversized windows:</h3>
<p>Uncheck the following key in gconf-editor:</p>
<code>
/apps/compiz/plugins/move/allscreens/options/constrain_y
</code>
<p>Now you can Alt-left-click any window and drag it around even above the top of the screen.</p>

<h3>Firefox:</h3>
<ul>
	<li>Move the bookmarks bar up to the file menu bar and get rid of the bookmarks bar:
           <ul>
            <li>Right click on the Home button and click customize.</li>
            <li>Your bookmarklets should now disappear and read "Bookmarks Toolbar items."</li>
            <li>Drag "Bookmarks Toolbar items" along the right hand side of the File .. Edit .... Help menus.
            <li>Click "Done."</li>
            <li>Right click on the now empty bookmarks toolbar and uncheck "Bookmarks Toolbar."</li>
           </ul>
         </li>
         <li>Get rid of the status bar: Go to View -> uncheck "Status Bar."</li>
         <li>Install a theme that uses smaller buttons and text: I like <a href="https://addons.mozilla.org/en-US/firefox/addon/3699">Classic Compact.</a></li>
	<li>Remember that Firefox has a nice fullscreen option : F11.</li>
        <li>Check out <a href="https://addons.mozilla.org/en-US/firefox/addon/5890">Tree Style Tabs</a>. It puts the tabs vertically on the left side of the browser and visually keeps track of what sites you were at that prompted you to open a new tab, all in a tree like fashion.</li>
</ul>

<p>Here is the desktop with gnome panel completely hidden and one terminal with menu bar hidden (click to see native size):</p>
<a href="/blog-post-images/hr-desktop-with-terminal.png"><img src="/blog-post-images/hr-desktop-with-terminal.png" alt="" title="hr-desktop-with-terminal" width="550" class="alignnone size-medium wp-image-261" /></a>

<p>Here is firefox maximised with two tabs open (click to see native size):</p>
<a href="/blog-post-images/hr-firefox-maximized.png"><img src="/blog-post-images/hr-firefox-maximized.png" alt="" title="hr-firefox-maximized" width="550" class="alignnone size-medium wp-image-260" /></a>

<p>Here is firefox in fullscreen (click to see native size):</p>
<a href="/blog-post-images/hr-firefox-fullscreen.png"><img src="/blog-post-images/hr-firefox-fullscreen.png" alt="" title="hr-firefox-fullscreen" width="550" class="alignnone size-medium wp-image-259" /></a>

<p>Firefox maximized with <a href="https://addons.mozilla.org/en-US/firefox/addon/5890">Tree Style Tabs</a>: </p>
<a href="/blog-post-images/hr-firefox-tree-style-tabs.png"><img src="/blog-post-images/hr-firefox-tree-style-tabs.png" alt="" title="hr-firefox-tree-style-tabs" width="550" class="alignnone size-medium wp-image-275" /></a>]]></content:encoded>
    </item>
    <item>
      <title>Emacs IRC (ERC) with Noticeable Notifications</title>
      <link>http://www.enigmacurry.com/2008/08/07/emacs-irc-erc-with-noticeable-notifications/</link>
      <pubDate>Thu, 07 Aug 2008 00:35:50 EDT</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Lisp]]></category>
      <category><![CDATA[Emacs]]></category>
      <category><![CDATA[Linux]]></category>
      <guid>http://www.enigmacurry.com/?p=151</guid>
      <description>Emacs IRC (ERC) with Noticeable Notifications</description>
      <content:encoded><![CDATA[
<p>I use <a href="http://www.emacswiki.org/cgi-bin/wiki?action=browse;oldid=EmacsIRCClient;id=ERC">ERC </a> for all my IRC chatting. I finally got fed up with not noticing someones message because I didn't have emacs focused. So I spent my evening concocting a more noticeable messaging system through Pymacs and libnotify.</p>

<p>Half way though implementing this, wouldn't you know it, I found <a href="http://www.emacswiki.org/cgi-bin/wiki/ErcPageMe">ErcPageMe</a> which does exactly what I wanted. I figured I was learning quite a bit and I continued writing my own version. I expanded on their code and (at least for me) made some improvements. So kudos go to whoever wrote ErcPageMe :)</p>

<p>The following code will pop up a message on your gnome desktop alerting you whenever you receive a personal message or when someone mentions your nickname in a channel. It also avoids notification for the same user in the same channel if they triggered a message within the last 30 seconds.</p>

<center> <img src="/blog-post-images/Emacs-ERC-Notification.png" alt="Emacs ERC Notification through libnotify" /></center>

<p>Here is my lisp and embedded python/pymacs code:</p>


<div class="pygments_murphy"><pre><span class="p">(</span><span class="nb">defun</span> <span class="nv">notify-desktop</span> <span class="p">(</span><span class="nv">title</span> <span class="nv">message</span> <span class="k">&amp;optional</span> <span class="nv">duration</span> <span class="k">&amp;optional</span> <span class="nv">icon</span><span class="p">)</span>
  <span class="s">&quot;Pop up a message on the desktop with an optional duration (forever otherwise)&quot;</span>
  <span class="p">(</span><span class="nv">pymacs-exec</span> <span class="s">&quot;import pynotify&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">pymacs-exec</span> <span class="s">&quot;pynotify.init(&#39;Emacs&#39;)&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="k">if</span> <span class="nv">icon</span> 
      <span class="p">(</span><span class="nv">pymacs-exec</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;msg = pynotify.Notification(&#39;%s&#39;,&#39;%s&#39;,&#39;%s&#39;)&quot;</span>
                           <span class="nv">title</span> <span class="nv">message</span> <span class="nv">icon</span><span class="p">))</span>
    <span class="p">(</span><span class="nv">pymacs-exec</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;msg = pynotify.Notification(&#39;%s&#39;,&#39;%s&#39;)&quot;</span> <span class="nv">title</span> <span class="nv">message</span><span class="p">))</span>
    <span class="p">)</span> 
  <span class="p">(</span><span class="k">if</span> <span class="nv">duration</span> 
      <span class="p">(</span><span class="nv">pymacs-exec</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;msg.set_timeout(%s)&quot;</span> <span class="nv">duration</span><span class="p">))</span>
    <span class="p">)</span>
  <span class="p">(</span><span class="nv">pymacs-exec</span> <span class="s">&quot;msg.show()&quot;</span><span class="p">)</span>
  <span class="p">)</span>

<span class="c1">;; Notify me when someone wants to talk to me.</span>
<span class="c1">;; Heavily based off of ErcPageMe on emacswiki.org, with some improvements.</span>
<span class="c1">;; I wanted to learn and I used my own notification system with pymacs</span>
<span class="c1">;; Delay is on a per user, per channel basis now.</span>
<span class="p">(</span><span class="nb">defvar</span> <span class="nv">erc-page-nick-alist</span> <span class="no">nil</span>
  <span class="s">&quot;Alist of &#39;nickname|target&#39; and last time they triggered a notification&quot;</span>
  <span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">erc-notify-allowed</span> <span class="p">(</span><span class="nv">nick</span> <span class="nv">target</span> <span class="k">&amp;optional</span> <span class="nv">delay</span><span class="p">)</span>
  <span class="s">&quot;Return true if a certain nick has waited long enough to notify&quot;</span>
  <span class="p">(</span><span class="nb">unless</span> <span class="nv">delay</span> <span class="p">(</span><span class="k">setq</span> <span class="nv">delay</span> <span class="mi">30</span><span class="p">))</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">cur-time</span> <span class="p">(</span><span class="nv">time-to-seconds</span> <span class="p">(</span><span class="nv">current-time</span><span class="p">)))</span>
        <span class="p">(</span><span class="nv">cur-assoc</span> <span class="p">(</span><span class="nb">assoc</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;%s|%s&quot;</span> <span class="nv">nick</span> <span class="nv">target</span><span class="p">)</span> <span class="nv">erc-page-nick-alist</span><span class="p">))</span>
        <span class="p">(</span><span class="nv">last-time</span><span class="p">))</span>
    <span class="p">(</span><span class="k">if</span> <span class="nv">cur-assoc</span>
        <span class="p">(</span><span class="k">progn</span>
          <span class="p">(</span><span class="k">setq</span> <span class="nv">last-time</span> <span class="p">(</span><span class="nb">cdr</span> <span class="nv">cur-assoc</span><span class="p">))</span>
          <span class="p">(</span><span class="nv">setcdr</span> <span class="nv">cur-assoc</span> <span class="nv">cur-time</span><span class="p">)</span>
          <span class="p">(</span><span class="nb">&gt;</span> <span class="p">(</span><span class="nb">abs</span> <span class="p">(</span><span class="nb">-</span> <span class="nv">cur-time</span> <span class="nv">last-time</span><span class="p">))</span> <span class="nv">delay</span><span class="p">))</span>
      <span class="p">(</span><span class="nb">push</span> <span class="p">(</span><span class="nb">cons</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;%s|%s&quot;</span> <span class="nv">nick</span> <span class="nv">target</span><span class="p">)</span> <span class="nv">cur-time</span><span class="p">)</span> <span class="nv">erc-page-nick-alist</span><span class="p">)</span>
      <span class="no">t</span><span class="p">)</span>
    <span class="p">)</span>
  <span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">erc-notify-PRIVMSG</span> <span class="p">(</span><span class="nv">proc</span> <span class="nv">parsed</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">nick</span> <span class="p">(</span><span class="nb">car</span> <span class="p">(</span><span class="nv">erc-parse-user</span> <span class="p">(</span><span class="nv">erc-response.sender</span> <span class="nv">parsed</span><span class="p">))))</span>
	<span class="p">(</span><span class="nv">target</span> <span class="p">(</span><span class="nb">car</span> <span class="p">(</span><span class="nv">erc-response.command-args</span> <span class="nv">parsed</span><span class="p">)))</span>
	<span class="p">(</span><span class="nv">msg</span> <span class="p">(</span><span class="nv">erc-response.contents</span> <span class="nv">parsed</span><span class="p">)))</span>
    <span class="c1">;;Handle true private/direct messages (non channel)</span>
    <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">not</span> <span class="p">(</span><span class="nv">erc-is-message-ctcp-and-not-action-p</span> <span class="nv">msg</span><span class="p">))</span>
               <span class="p">(</span><span class="nv">erc-current-nick-p</span> <span class="nv">target</span><span class="p">)</span>
	       <span class="p">(</span><span class="nv">erc-notify-allowed</span> <span class="nv">nick</span> <span class="nv">target</span><span class="p">)</span>
	       <span class="p">)</span>
      <span class="c1">;Do actual notification</span>
      <span class="p">(</span><span class="nv">ding</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">notify-desktop</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;%s - %s&quot;</span> <span class="nv">nick</span>
                              <span class="p">(</span><span class="nv">format-time-string</span> <span class="s">&quot;%b %d %I:%M %p&quot;</span><span class="p">))</span>
                      <span class="nv">msg</span> <span class="mi">0</span> <span class="s">&quot;gnome-emacs&quot;</span><span class="p">)</span>
      <span class="p">)</span>
    <span class="c1">;;Handle channel messages when my nick is mentioned</span>
    <span class="p">(</span><span class="nb">when</span> <span class="p">(</span><span class="nb">and</span> <span class="p">(</span><span class="nb">not</span> <span class="p">(</span><span class="nv">erc-is-message-ctcp-and-not-action-p</span> <span class="nv">msg</span><span class="p">))</span>
               <span class="p">(</span><span class="nv">string-match</span> <span class="p">(</span><span class="nv">erc-current-nick</span><span class="p">)</span> <span class="nv">msg</span><span class="p">)</span>
               <span class="p">(</span><span class="nv">erc-notify-allowed</span> <span class="nv">nick</span> <span class="nv">target</span><span class="p">)</span>
	       <span class="p">)</span>
      <span class="c1">;Do actual notification</span>
      <span class="p">(</span><span class="nv">ding</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">notify-desktop</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;%s - %s&quot;</span> <span class="nv">target</span>
                              <span class="p">(</span><span class="nv">format-time-string</span> <span class="s">&quot;%b %d %I:%M %p&quot;</span><span class="p">))</span>
                      <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;%s: %s&quot;</span> <span class="nv">nick</span> <span class="nv">msg</span><span class="p">)</span> <span class="mi">0</span> <span class="s">&quot;gnome-emacs&quot;</span><span class="p">)</span>
      <span class="p">)</span>
    <span class="p">)</span>
      
  <span class="p">)</span>

<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;erc-server-PRIVMSG-functions</span> <span class="ss">&#39;erc-notify-PRIVMSG</span><span class="p">)</span>
</pre></div>



]]></content:encoded>
    </item>
    <item>
      <title>cycle_xrandr.py : dual and single displays on Ubuntu</title>
      <link>http://www.enigmacurry.com/2008/07/10/cycle_xrandrpy-dual-and-single-displays-on-ubuntu/</link>
      <pubDate>Thu, 10 Jul 2008 06:24:22 EDT</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Linux]]></category>
      <guid>http://www.enigmacurry.com/?p=149</guid>
      <description>cycle_xrandr.py : dual and single displays on Ubuntu</description>
      <content:encoded><![CDATA[
<p>Linux power management has gotten good recently. My last two laptops (HP dv9000 and Macbook Pro) have supported hardware suspend mode out of the box. I'm impressed!</p>

<p>Being that I hardly ever turn off the laptop (I just suspend now) I'm left with an annoyance: I use two displays at work and one everywhere else. In Ubuntu, I was easily able to setup dual and single modes such that when I boot up, Xorg detects how many displays are connected appropriately. But now that I don't turn off the machine, I want to be able to just plug in another monitor and go. I don't want to have to reboot the computer. I don't even want to have to log out. I want to plug the monitor in, leave all my apps running and in the state they are in.</p>

<p>Xrandr does this and it works great. But what if I'm in dual display mode but I only actually have one monitor connected? Can I get to an open terminal to use xrandr? Easily? Probably not.</p>

<p>I wrote the following python script to take care of this. It detects all of the modes that xrandr knows about and cycles to the next size listed. I then bind this script to a <a href="http://www.howtogeek.com/howto/ubuntu/assign-custom-shortcut-keys-on-ubuntu-linux/">custom keyboard shortcut</a> so I don't have to type or even see anything on the screen:</p>


<div class="pygments_murphy"><pre><span class="c">#!/usr/bin/env python</span>
<span class="c"># -*- coding: utf-8 -*-</span>

<span class="n">__author__</span> <span class="o">=</span> <span class="s">&quot;Ryan McGuire (ryan@enigmacurry.com)&quot;</span>
<span class="n">__date__</span>   <span class="o">=</span> <span class="s">&quot;Thu Jul 10 15:27:18 2008&quot;</span>

<span class="sd">&quot;&quot;&quot;Cycle through all screen resolutions detected by xrandr&quot;&quot;&quot;</span>

<span class="kn">from</span> <span class="nn">subprocess</span> <span class="kn">import</span> <span class="n">Popen</span><span class="p">,</span> <span class="n">PIPE</span>
<span class="kn">import</span> <span class="nn">re</span>

<span class="n">size_re</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="s">&quot;^   ([0-9]*x[0-9]*)\W*[0-9]*\.[0-9]*(\*)?&quot;</span><span class="p">)</span>

<span class="k">def</span> <span class="nf">list_sizes</span><span class="p">():</span>
    <span class="sd">&quot;&quot;&quot;List all sizes detected by xrandr,</span>
<span class="sd">    ordered by the next resolution to cycle to&quot;&quot;&quot;</span>
    <span class="n">p1</span> <span class="o">=</span> <span class="n">Popen</span><span class="p">([</span><span class="s">&#39;xrandr&#39;</span><span class="p">],</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">)</span>
    <span class="n">sizes</span> <span class="o">=</span> <span class="p">[]</span>
    <span class="n">current_size_index</span> <span class="o">=</span> <span class="mi">0</span>
    <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span>  <span class="n">p1</span><span class="o">.</span><span class="n">communicate</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">):</span>
        <span class="n">m</span> <span class="o">=</span> <span class="n">size_re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
        <span class="k">if</span> <span class="n">m</span><span class="p">:</span>
            <span class="n">sizes</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span>
            <span class="k">if</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="o">==</span> <span class="s">&quot;*&quot;</span><span class="p">:</span>
                <span class="n">current_size_index</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">sizes</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span>
    <span class="k">return</span> <span class="n">sizes</span><span class="p">[</span><span class="n">current_size_index</span><span class="o">+</span><span class="mi">1</span><span class="p">:]</span> <span class="o">+</span> <span class="n">sizes</span><span class="p">[:</span><span class="n">current_size_index</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>

<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">&#39;__main__&#39;</span><span class="p">:</span>
    <span class="n">Popen</span><span class="p">([</span><span class="s">&#39;xrandr&#39;</span><span class="p">,</span><span class="s">&#39;-s&#39;</span><span class="p">,</span><span class="n">list_sizes</span><span class="p">()[</span><span class="mi">0</span><span class="p">]])</span>
</pre></div>



]]></content:encoded>
    </item>
    <item>
      <title>New Slacker Screenlet released</title>
      <link>http://www.enigmacurry.com/2008/04/04/new-slacker-screenlet-released/</link>
      <pubDate>Fri, 04 Apr 2008 22:43:59 EDT</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Linux]]></category>
      <guid>http://www.enigmacurry.com/2008/04/04/new-slacker-screenlet-released/</guid>
      <description>New Slacker Screenlet released</description>
      <content:encoded><![CDATA[
<p>Check it out: I updated my <a href="http://screenlets.org/index.php/Slacker">Slacker Screenlet</a> today.</p>

<p>New in this version:</p>
<ul>
	<li>Bug fixed where the screenlet-manager would respawn infinitely</li>
	<li>Integrated LastSlacker support</li>
</ul>

<p>You can read more about the <a href="/2007/11/20/slacker-screenlet/">original version in my previous post.</a></p>

<p><a href="http://lastslacker.com">LastSlacker</a> is a way to scrobble what you listen to on <a href="http://last.fm">Last.FM</a>. This lets you share a log of what you listen to with friends. I've been meaning to add this feature for a long time now, until today it's been in a sorta working state for months! It feels good to have finally gotten this project pretty much finished.</p>

]]></content:encoded>
    </item>
    <item>
      <title>Backing up my (online) brain</title>
      <link>http://www.enigmacurry.com/2008/02/22/backing-up-my-online-brain/</link>
      <pubDate>Fri, 22 Feb 2008 23:22:59 EST</pubDate>
      <category><![CDATA[Backups]]></category>
      <category><![CDATA[Gmail]]></category>
      <category><![CDATA[Linux]]></category>
      <guid>http://www.enigmacurry.com/2008/02/22/backing-up-my-online-brain/</guid>
      <description>Backing up my (online) brain</description>
      <content:encoded><![CDATA[
<p>Files from my computer are disappearing.</p>

<p>No worries though, this is intentional. </p>

<p>As time goes on, more and more of my files are ending up in places like:</p>

<ul>
 <li>Google</li>
 <li>Flickr</li>
 <li>Del.icio.us</li>
 <li>Facebook</li>
</ul>

<p>And things are great. I can access these services from anywhere in the world, from any computer. What a great time to be alive!</p>

<p>But there is a bit of uneasiness in the back of my mind about all of this. Yes, these services liberate me (as well as my data), but at the same time, I've become a new breed of slave -- my data is no longer mine to control.</p>

<p>Privacy concerns aside, the biggest thing that haunts me is what if one of these services were to blow up? My data would be gone. When the data resided on my computer I could back it up myself anytime I wanted and have some sense of safety. With data on Google's server, honestly I feel pretty darn safe, but the cost of losing my data is still quite high.</p>

<p><b>My goal: Get my data back into my hands.</b></p>

<p>I'd like to start writing up my experiences on wrangling all of my data from my online services back onto media I control.</p>

<p>If you want to follow along, I'll be tagging these posts <a href="/category/backups">'Backups'</a>.</p>

<h3>Gmail</h3>

<p>The first service I'll start with is Gmail. Google, in the realm of free mail hosts, is very accommodating when it comes to accessing your mail in bulk. They have both POP3 and IMAP access. Retrieving your mail with <a href="https://mail.google.com/support/bin/answer.py?answer=12103">any number of clients</a> is trivial.</p>

<p>But there's more to Gmail than just your email: tags. POP3 won't get the tags, but IMAP will organize tags into folders. However, most IMAP clients only download messages on-the-fly as you read them, not all at once (like for backups).</p>

<p>Solution: <a href="http://software.complete.org/offlineimap">OfflineIMAP</a>.</p>

<p>OfflineIMAP will completely download all your Gmail messages into folders corresponding to all your tags. It actually does much more than this, OfflineIMAP is a full two-way synchronization of your email. Once you've downloaded your email you can take it with you while you're offline, read it, delete it and when you come back online you synchronize with gmail again deleting those same messages off of the server and retrieving new messages. </p>

<p>OfflineIMAP works really well for it's stated purpose: using IMAP offline. It is also useful for backing up IMAP accounts but you <b>have to understand how it works</b> so that you don't accidentally start deleting mail from your gmail account. Since we're using OfflineIMAP as a <i>backup</i> device instead of a tool to read our email I would recommend that you never open the email that it downloads with any sort of mail reader. If you do, and you accidentally move messages to a different location (mutt does this to read messages for instance), OfflineIMAP might think you deleted the message <b>and it will delete the same message off your server</b> (In Gmail's case it actually just removes the tag and keeps the message in All Mail, but still..) If you ever need to use the downloaded email, its safer to use a copy instead.</p>

<p>Caveat Emptor. Onward to configuring OfflineIMAP.</p>

On Ubuntu:

<div class="pygments_murphy"><pre>sudo apt-get install offlineimap
</pre></div>




<p>Create a file called ~/.offlineimaprc :</p>


<div class="pygments_murphy"><pre>[general]
accounts = GMail
maxsyncaccounts = 3

[Account GMail]
localrepository = Local
remoterepository = Remote

[Repository Local]
type = Maildir
localfolders = /storage/Gmail_Backup

[Repository Remote]
type = IMAP
remotehost = imap.gmail.com
remoteuser = your_username@gmail.com
remotepass = your_password
ssl = yes
maxconnections = 1

#Setting realdelete = yes will Really Delete email from the server.
#Otherwise &quot;deleting&quot; a message will just remove any labels and 
#retain the message in the All Mail folder.
realdelete = no
</pre></div>




<p>The things you need to change are:</p>
<ul>
 <li>localfolders - This is the full path to where it will save the email</li>
 <li>remoteuser - This is your gmail email address</li>
 <li>remotepass - This is your gmail password (required for automated backups, otherwise it asks everytime)</li>
</ul>

<p>You can now run offlineimap and you should start to see it download your email. By default, OfflineIMAP gives you a graphical or textual interface that shows you what it is doing. This is good especially for the first time you download your email.</p>

<p>After you've downloaded all of your email, you'll want to automate the task so it runs at least every day:</p>

<p>Put the following in your <a href="http://ubuntuforums.org/showthread.php?t=102626">crontab</a>:</p>
<pre lang="text">
00 23 * * * offlineimap -u Noninteractive.Quiet
</pre>

<p>This will run OfflineIMAP everyday at 11PM.</p>

<p>Again, because OfflineIMAP is not technically a backup solution in itself, you might also care to make a seperate rsyncd copy of the mail somewhere else:</p>

<pre lang="text">
rsync -a /storage/Gmail_Backup/ /storage/Gmail_Backup_Copy
</pre>

<p>You can similarly run rsync in your crontab after your offlineimap finishes. By making this seperate copy, you avoid the possible deletion of emails by OfflineIMAP. This second copy will also retain messages that you delete later on in Gmail (The offlineimap syncd copy will not). This may or may not be what you want.</p>

<p>Stay tuned for the next installment: Flickr backups!</p>
]]></content:encoded>
    </item>
    <item>
      <title>Slacker Screenlet</title>
      <link>http://www.enigmacurry.com/2007/11/20/slacker-screenlet/</link>
      <pubDate>Tue, 20 Nov 2007 12:54:44 EST</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Linux]]></category>
      <guid>http://www.enigmacurry.com/2007/11/20/slacker-screenlet/</guid>
      <description>Slacker Screenlet</description>
      <content:encoded><![CDATA[
<a href="/blog-post-images/SlackerScreenletDemo.png"><img src="/blog-post-images/SlackerScreenletDemoSmall.jpg" alt="Showing of the Slacker Screenlet" /></a>

<p>Having an absurdly large music collection can sometimes have it's downsides. <a href="http://www.slacker.com">Slacker</a> is a nice way to listen to music when you can't decide what to listen to. Like with Pandora or Last.fm, you can create your own radio station by telling the player what kind of music you like and the player will automatically choose music to play for you. With Slacker, you can customize how much or how little new music you want to allow into the mix, which is the main reason I prefer it over Pandora.</p>

<p>On Windows, Slacker has created a nice standalone player. On Linux or Mac you're stuck with the web player.  The nice thing about a standalone player is it won't interfere with my habit of closing my browser (thus killing my music). I decided I needed to find a way to separate the player from my main browser.</p>

<p><a href="http://www.screenlets.org">Screenlets</a> are little, graphical,  single-purpose eye-candy (written in Python :)).  They can do things like show you the time or the current weather forecast, CPU load, the word of the day etc. Compiz allows these applications to run in their own layer such that they can appear and disappear quickly with the press of a button. They are quick and easy to get to, but stay out of your way when not needed.</p>

<p>I decided a screenlet for Slacker would be ideal, so I wrote one.</p>

<p>You can <a href="http://www.gnome-look.org/content/download.php?content=70166&id=1&tan=10147278">download my Slacker Screenlet</a> for yourself.</p>

<p>Also see the following:</p>
<ul>
	<li><a href="http://screenlets.org/index.php?title=Slacker">Screenlets.org page</a></li>
	<li><a href="http://www.gnome-look.org/content/show.php?content=70166">Gnome-look page</a></li>
</ul>


]]></content:encoded>
    </item>
    <item>
      <title>Building Multi-TTY Emacs from CVS on Ubuntu Gutsy Gibbon</title>
      <link>http://www.enigmacurry.com/2007/10/21/building-multi-tty-emacs-from-cvs-on-ubuntu-gusty-gibbon/</link>
      <pubDate>Sun, 21 Oct 2007 18:25:26 EDT</pubDate>
      <category><![CDATA[Emacs]]></category>
      <category><![CDATA[Linux]]></category>
      <guid>http://www.enigmacurry.com/2007/10/21/building-multi-tty-emacs-from-cvs-on-ubuntu-gusty-gibbon/</guid>
      <description>Building Multi-TTY Emacs from CVS on Ubuntu Gutsy Gibbon</description>
      <content:encoded><![CDATA[
<p><em>(Historical note May 2008: The build instructions below, while they should still work, are unnecessary as Multi-TTY has been merged into the main Emacs 23 branch and is available in ubuntu repositories: apt-get install emacs-snapshot) </em></p>

<p>Last spring I wrote an article about <a href="http://www.enigmacurry.com/2007/05/24/multi-tty-emacs-on-gentoo-and-ubuntu/">Multi-TTY Emacs</a>. I had promised that I would update instructions for building it on Ubuntu, but since then I have been mainly using Gentoo on my laptop and never got around to updating it. Sorry :)</p>

<p>I switched to Ubuntu Gutsy Gibbon yesterday. I also got Multi-TTY Emacs running, and here's the video to prove it (If this is too small to see, <a href="/blog-post-files/Showing off Multi-TTY Emacs on Ubuntu Gutsy Gibbon.ogm">download the original ogg theora version</a>) :</p>

<embed type="application/x-shockwave-flash" src="/flash/flvplayer.swf" style="" id="player1" name="player1" quality="high" wmode="transparent" allowscriptaccess="always" allowfullscreen="true" flashvars="height=448&amp;width=570&amp;file=/blog-post-files/Showing%20off%20Multi-TTY%20Emacs%20on%20Ubuntu%20Gutsy%20Gibbon.flv&amp;link=http://www.enigmacurry.com/blog-post-files/Showing%20off%20Multi-TTY%20Emacs%20on%20Ubuntu%20Gutsy%20Gibbon.flv" height="448" width="570">

<h3>Building CVS Emacs the old fashioned way</h3>

<p>For those of you that want the easy way out, I've <a href="/blog-post-files/emacs-cvs-multitty-102107.deb">prebuilt an emacs CVS package that includes the Multi-TTY patch</a>. I've tested that the package works on both Gutsy as well as Feisty.</p>

<p>For those of you that would like to learn how this is done, here's my recipe:</p>

<p>Install all the dependencies</p>

<div class="pygments_murphy"><pre>sudo apt-get install build-essential cvs texinfo libx11-dev libxpm-dev libjpeg-dev <span class="se">\</span>
libpng-dev libgif-dev libtiff-dev libgtk2.0-dev checkinstall
</pre></div>



<p>Check out the Emacs code from CVS</p>

<div class="pygments_murphy"><pre>cvs -z3 -d:pserver:anonymous@cvs.savannah.gnu.org:/cvsroot/emacs co emacs
</pre></div>



<p>Compile the source</p>

<div class="pygments_murphy"><pre><span class="nb">cd </span>emacs
./configure --with-gtk --prefix<span class="o">=</span>/usr/local
make bootstrap
make
</pre></div>



<p>Checkinstall will build a basic emacs package for us with a minimum of fuss. We don't want to automatically install this package though for reasons we'll see below</p>

<div class="pygments_murphy"><pre>sudo checkinstall -D --install<span class="o">=</span>no
</pre></div>



<p>Checkinstall will ask you to change some values. I changed the maintainer email and the version number.</p>

<p>Checkinstall is great, and works for 99% percent of the packages that I've tried it with. Emacs is a bit different though -- the package that checkinstall creates doesn't include everything that emacs requires, like all the .el files in the lisp folder among other things. So we have to edit the package a bit. For the following code, we'll assume the .deb file that checkinstall creates is just called "emacs_cvs-10202007-1_i386.deb", so adjust for whatever checkinstall called your .deb file:</p>

<p>Extract the data from the .deb</p>

<div class="pygments_murphy"><pre>dpkg-deb -x emacs_cvs-10202007-1_i386.deb emacs_cvs-10202007-1_i386 
<span class="c">#Or whatever your .deb is called</span>
</pre></div>



<p>Extract the control information from the .deb</p>

<div class="pygments_murphy"><pre>dpkg-deb -e emacs_cvs-10202007-1_i386.deb emacs_cvs-10202007-1_i386/DEBIAN
</pre></div>



<p>Now we need to add some of the files that checkinstall left out of the package</p>

<div class="pygments_murphy"><pre>cp -a lisp/* emacs_cvs-10202007-1_i386/usr/local/share/emacs/23.0.50/site-lisp/
mkdir emacs_cvs-10202007-1_i386/usr/local/share/emacs/23.0.50/lisp
mkdir -p emacs_cvs-10202007-1_i386/usr/local/libexec/emacs/23.0.50/i686-pc-linux-gnu
cp -a etc emacs_cvs-10202007-1_i386/usr/local/share/emacs/23.0.50/
mkdir emacs_cvs-10202007-1_i386/etc
ln -s ../usr/local/share/emacs/23.0.50/etc/termcap.src emacs_cvs-10202007-1_i386/etc/termcap
</pre></div>



<p>Rebuild the modified package</p>

<div class="pygments_murphy"><pre>dpkg-deb -b emacs_cvs-10202007-1_i386 emacs_modified.deb
</pre></div>




<p>To totally revolutionize the way you use Emacs, remember to check out <a href="http://www.enigmacurry.com/2007/05/24/multi-tty-emacs-on-gentoo-and-ubuntu/">my earlier post on Multi-TTY Emacs</a>.</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
