<?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>Fri, 01 Jul 2011 16:53:59 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>PHP Code Compliance In Emacs</title>
      <link>http://www.enigmacurry.com/2011/07/01/php-code-compliance-in-emacs</link>
      <pubDate>Fri, 01 Jul 2011 09:00:00 EDT</pubDate>
      <category><![CDATA[php]]></category>
      <category><![CDATA[emacs]]></category>
      <guid>S3pGCFLQEPa-eWEQfIcHONGFTCQ=</guid>
      <description>PHP Code Compliance In Emacs</description>
      <content:encoded><![CDATA[<p>My job has me working on a project in PHP right now -- it sure isn't
Python, but PHP has grown up considerably since the last time I used
it, which has been <em>awhile</em>. Consequently, I have no Emacs config for
PHP setup, other than vanilla php-mode, so I went in search of
one. Of course, I knew <a href="http://sachachua.com/blog/2008/07/emacs-and-php-on-the-fly-syntax-checking-with-flymake/">Sacha Chua would have a great
one</a>, so
that's where I've started.</p>
<p>My code is required to conform to the <a href="http://pear.php.net/manual/en/standards.php">PEAR coding
standards</a> which is a bit
pedantic in places, but it's generally a good reference to make clean
and readable code. The only real pain in conforming to a coding
standard is if your editor doesn't pick up on your mistakes right
away, you get no automatic feedback and you're left with the task of
cleaning up your code later at an inconvenient time. In my case, a
subversion pre-commit hook checks for compliance and prevents me from
checking in non-conforming code just when I thought I was ready to go
home!</p>
<p>Sacha's configuration only checks for general syntax errors, it
doesn't check for code compliance. For that, I'm using
<a href="http://pear.php.net/package/PHP_CodeSniffer/redirected">PHP_CodeSniffer</a>
which performs a static analysis of a PHP file and notes any
deviations for a given standard. They even <a href="http://pear.php.net/manual/en/package.php.php-codesniffer.reporting.php">support Emacs compile
mode</a>
out of the box. Compile mode still doesn't give me automatic feedback
though, for that I still wanted to use flymake like Sacha has.</p>
<p>So here's my elisp for configuring Emacs to automatically highlight
both syntax errors and coding standard deviations for PHP:</p>
<div class="pygments_murphy"><pre><span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;php-mode</span><span class="p">)</span>
<span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;flymake</span><span class="p">)</span>

<p><span class="c1">;; Pear coding standards : http://pear.php.net/manual/en/standards.indenting.php</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">pear/php-mode-init</span> <span class="p">()</span>
  <span class="s">&quot;Set some buffer-local variables.&quot;</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">case-fold-search</span> <span class="no">t</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">indent-tabs-mode</span> <span class="no">nil</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">fill-column</span> <span class="mi">78</span><span class="p">)</span>
  <span class="p">(</span><span class="k">setq</span> <span class="nv">c-basic-offset</span> <span class="mi">4</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">c-set-offset</span> <span class="ss">&#39;arglist-cont</span> <span class="mi">0</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">c-set-offset</span> <span class="ss">&#39;arglist-intro</span> <span class="ss">&#39;+</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">c-set-offset</span> <span class="ss">&#39;case-label</span> <span class="mi">2</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">c-set-offset</span> <span class="ss">&#39;arglist-close</span> <span class="mi">0</span><span class="p">))</span>
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;php-mode-hook</span> <span class="ss">&#39;pear/php-mode-init</span><span class="p">)</span></p>
<p><span class="p">(</span><span class="nb">defun</span> <span class="nv">my-php-hook-function</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;compile-command</span><span class="p">)</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;php_lint %s&quot;</span> <span class="p">(</span><span class="nv">buffer-file-name</span><span class="p">))))</span>
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;php-mode-hook</span> <span class="ss">&#39;my-php-hook-function</span><span class="p">)</span></p>
<p><span class="p">(</span><span class="nb">defun</span> <span class="nv">flymake-php-init</span> <span class="p">()</span>
  <span class="s">&quot;Use php and phpcs to check the syntax and code compliance of the current file.&quot;</span>
  <span class="p">(</span><span class="k">let*</span> <span class="p">((</span><span class="nv">temp</span> <span class="p">(</span><span class="nv">flymake-init-create-temp-buffer-copy</span> <span class="ss">&#39;flymake-create-temp-inplace</span><span class="p">))</span>
     <span class="p">(</span><span class="nv">local</span> <span class="p">(</span><span class="nv">file-relative-name</span> <span class="nv">temp</span> <span class="p">(</span><span class="nv">file-name-directory</span> <span class="nv">buffer-file-name</span><span class="p">))))</span>
    <span class="p">(</span><span class="nb">list</span> <span class="s">&quot;php_lint&quot;</span> <span class="p">(</span><span class="nb">list</span> <span class="nv">local</span><span class="p">))))</span></p>
<p><span class="c1">;;This is the error format for : php -f somefile.php -l </span>
<span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;flymake-err-line-patterns</span>
  <span class="o">&#39;</span><span class="p">(</span><span class="s">&quot;\(Parse\|Fatal\) error: +\(.<em>?\) in \(.</em>?\) on line \([0-9]+\)$&quot;</span> <span class="mi">3</span> <span class="mi">4</span> <span class="no">nil</span> <span class="mi">2</span><span class="p">))</span></p>
<p><span class="p">(</span><span class="nv">add-to-list</span> <span class="ss">&#39;flymake-allowed-file-name-masks</span> <span class="o">&#39;</span><span class="p">(</span><span class="s">&quot;\.php$&quot;</span> <span class="nv">flymake-php-init</span><span class="p">))</span>
<span class="p">(</span><span class="nv">add-hook</span> <span class="ss">&#39;php-mode-hook</span> <span class="p">(</span><span class="k">lambda</span> <span class="p">()</span> <span class="p">(</span><span class="nv">flymake-mode</span> <span class="mi">1</span><span class="p">)))</span>
</pre></div></p>
<p>This depends on a small BASH helper script which I have stored in my
$HOME/bin directory (which is on my PATH by default):</p>
<div class="pygments_murphy"><pre>!/bin/bash
<span class="c">#This does standard PHP syntax checking</span>
php -f <span class="nv">$1</span> -l
<span class="c">#This does coding standard checking</span>
phpcs --standard<span class="o">=</span>PEAR --report<span class="o">=</span>emacs <span class="nv">$1</span>
<span class="c">#Always exit with status code 0 otherwise flymake complains</span>
<span class="nb">exit </span>0
</pre></div>

<p>Now I get nice red highlighting for when I forget a doc tag or to put a space
between parens and brackets. Isn't pedantry great? :/ </p>
<p><center><img src="/blog-post-images/PHP Code Compliance.png"></center></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>My Emacs config on Github</title>
      <link>http://www.enigmacurry.com/2009/01/19/my-emacs-config-on-github/</link>
      <pubDate>Mon, 19 Jan 2009 17:01:56 EST</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[emacs]]></category>
      <guid>http://www.enigmacurry.com/?p=376</guid>
      <description>My Emacs config on Github</description>
      <content:encoded><![CDATA[
<p>The most popular post on this blog is <a href="/2008/05/09/emacs-as-a-powerful-python-ide/">Emacs as a powerful Python IDE</a>. I get quite a few emails regarding that post and I realized the other day that I've done a lot of customizations to my .emacs, and subsequently that post is starting to get a little dated. Time is a curious creature, it seems like yesterday that I wrote that post, but it's been almost 9 months now.</p>

<p>I've been learning and playing around with <a href="http://git-scm.com">git</a> recently, so I've decided to post my <a href="http://www.github.com/EnigmaCurry/emacs">entire .emacs config on github</a>. </p>

<p>Here are the latest instructions for emulating my Emacs environment on Ubuntu 8.10:</p>
<ul>
  <li>Enable the <a href="http://help.ubuntu.com/community/Repositories/Ubuntu">universe repository</a></li>
  <li>sudo apt-get update</li>
  <li>sudo apt-get install emacs-snapshot git-core automake libgconf2-dev texinfo python-setuptools</li>
  <li>cd ~</li>
  <li>git clone git://github.com/EnigmaCurry/emacs .emacs.d</li>
  <li>cd ~/.emacs.d</li>
  <li>git submodule init</li>
  <li>git submodule update</li>
  <li>cd ~/.emacs.d/vendor</li>
  <li>./vendor-compile.sh</li>
  <li>sudo easy_install "http://downloads.sourceforge.net/rope/rope-0.9.1.tar.gz?modtime=1225268769&big_mirror=0"</li>
  <li>sudo easy_install "http://downloads.sourceforge.net/rope/ropemacs-0.6.tar.gz?modtime=1223039342&big_mirror=0"</li>  
</ul>

<p>I've done some reorganization of the directory structure: </p>
<ol>
  <li>There actually is no ~/.emacs file anymore, having realized that Emacs looks for ~/.emacs.d/init.el. Convenient! </li>
  <li>All third party packages are now installed in ~/.emacs.d/vendor. This was a great tip I saw in the <a href="http://peepcode.com/products/meet-emacs">Emacs Peepcode screencast</a>. (it's $9, but worth it).</li>
  <li>I've taken the suggestion that greg made in the comments to use submodules for some of the vendor packages. The vendor-compile.sh script does the compiling of those packages.</li>
<li>All private code goes in ~/.emacs.private. This lets me keep passwords and such outside of the main git repository and allows me to publish my config more easily. Before I did this I had to spend time sanitizing the code before each release.</li>
</ol>

<p>I have appreciated your many encouraging Emails and comments. :)</p>]]></content:encoded>
    </item>
    <item>
      <title>Extending Emacs with Advice</title>
      <link>http://www.enigmacurry.com/2009/01/14/extending-emacs-with-advice/</link>
      <pubDate>Wed, 14 Jan 2009 16:30:10 EST</pubDate>
      <category><![CDATA[emacs]]></category>
      <guid>http://www.enigmacurry.com/?p=338</guid>
      <description>Extending Emacs with Advice</description>
      <content:encoded><![CDATA[
<p>The greatest single thing about Emacs is it's extensibility. If you think Emacs is missing something, or don't like how something works, you can change it. But that's true of any open-source software. The difference with Emacs is how easy it is to make that change. </p>

<p>There are several different strategies to extend Emacs. I'll list a few of them in order of hardest to easiest (and arguably from worst to best):</p>
<ul>
  <li>Write your own <a href="http://www.emacswiki.org/emacs/MajorMode">major</a> or <a href="http://www.emacswiki.org/emacs/MinorMode">minor mode</a> from scratch.</li>
  <li>Edit someone else's mode (and hopefully submit a patch.)</li>
  <li>Write an <a href="http://www.delorie.com/gnu/docs/elisp-manual-21/elisp_212.html">Advice</a> function.</li>
  <li>Write a <a href="http://www.emacswiki.org/emacs/ModeHooks">Mode Hook</a>.</li>
</ul>

<h2 class="intrablog">Where Advice fits in</h2>
<p><small>(Don't worry, I get into the meat of it in the next section. For the impatient, skip down.)</small></p>

<p>Mode hooks are almost always the easiest and best way to extend a particular mode, but they are also limited in scope. The author of the mode created these hooks specifically to allow you to extend his mode, and are therefore the best maintainable way to extend a mode (the author is unlikely to remove those hooks in future versions). However, if the author didn't anticipate certain functionality and there is no appropriate hook provided, you'll have to come up with a different solution.</p>

<p>At this point, obviously, you could just write your own mode -- but what a pain that would be if you already have something that's close to what you want. So why not just edit that particular mode to suit your needs (perhaps creating that missing mode hook yourself?) This approach is probably the best one especially if the feature you want is something other people would benefit from. You can submit your changes as a patch to the original author and (if he accepts them) your changes go into the next release.</p>

<p>But what if for some reason your changes are not acceptable to the author? You can still use your changes on your local machine, but every time a new version of the original mode comes out you'll have to merge your changes back into that new version. At this point you've successfully <a href="http://en.wikipedia.org/wiki/Fork_(software_development)">"forked"</a> the project, but that's usually a bad thing in the long run.</p>

<p>One other option exists to Emacs developers: advice. Advice allows you to wrap existing functions with your own functions. This allows some types of behavior to be modified without even having to change the original file at all. You can keep your changes completely separated in your own customized files. This gives you the benefit of inheriting new versions of the mode by simply downloading the new version and putting it in your load path. In most cases your advice function will continue to work on the new version and you didn't have to merge any changes at all. If significant changes have been made you may need to modify your advice function, or create a new one, but you still won't need to merge any changes. </p>

<p>Continue reading and I'll give you a real-world example of how I've used advice, but I want to first re-iterate the proper use cases of advice:</p>

<ul>
  <li>If you can use the mode hooks provided by the author, use them instead.</li>
  <li>If there is a bug in the original mode, just fix it in the original code and submit a patch.</li>
  <li>If there is a new feature you want, add it to the original mode and submit a patch. Talk to the author, work with him, and it will most likely end up in the next release.</li>
  <li>If you are an Emacs developer, working on Emacs itself, or one of the modes shipped with Emacs, <em>never</em> use advice. It's the least maintainable method of extending Emacs with the exception of a pure fork, and since you're working on Emacs itself, it's not a fork.</li>
  <li>If your patch is not accepted, or you know that what you want is fringe enough or hackish enough to not warrant submitting a patch, <em>only then</em> should you use advice or fork the project.</li>
</ul>

<h2 class="intrablog">Using Advice</h2>

<p>Alright, onward to the example I promised. I really liked the tip over at <a href="http://emacs.wordpress.com/2008/07/18/keeping-your-secrets-secret/">Minor Emacs Wizardry</a> on combining EasyPG with Org mode -- it's an awesome way to keep a lot of things in an organized and encrypted way -- I use it all the time now.</p>

<p>My main machine is running Ubuntu and it's default GnuPG agent is <a href="http://projects.gnome.org/seahorse/">Seahorse</a>. It's actually a pretty nice manager for encryption (SSH and PGP) and is completely integrated with the Gnome desktop. The one problem I have with it is that I use <a href="/2007/05/24/multi-tty-emacs-on-gentoo-and-ubuntu/">Multi-TTY Emacs</a> and when I'm using a terminal on a remote connection and I try and open an encrypted file, Seahorse pops up on the desktop instead of prompting me for the passphrase on my remote connection. In the past I've had to fire up VNC to my desktop just so that I could enter the password; damn inconvenient.</p>

<p>I could setup something like <a href="http://packages.ubuntu.com/intrepid/keychain">keychain</a>, it's a real nice GPG agent that works equally well on the desktop as on the console. I've used it in the past and liked it. Seahorse requires no setup though, it comes with Ubuntu by default, and like I said, I really quite like it.</p>

<p>So, when I'm on my remote connection and Seahorse doesn't have my password cached, I'd like to be able to bypass the GPG agent entirely and just enter my password. EasyPG doesn't appear to have this functionality so I added it with advice:</p>


<div class="pygments_murphy"><pre><span class="p">(</span><span class="nv">defadvice</span> <span class="nv">epg--start</span> <span class="p">(</span><span class="nv">around</span> <span class="nv">advice-epg-disable-agent</span> <span class="nv">disable</span><span class="p">)</span>
  <span class="s">&quot;Make epg--start not able to find a gpg-agent&quot;</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">agent</span> <span class="p">(</span><span class="nv">getenv</span> <span class="s">&quot;GPG_AGENT_INFO&quot;</span><span class="p">)))</span>
    <span class="p">(</span><span class="nv">setenv</span> <span class="s">&quot;GPG_AGENT_INFO&quot;</span> <span class="no">nil</span><span class="p">)</span>
    <span class="nv">ad-do-it</span>
    <span class="p">(</span><span class="nv">setenv</span> <span class="s">&quot;GPG_AGENT_INFO&quot;</span> <span class="nv">agent</span><span class="p">)))</span>
</pre></div>




<p>That little bit of code wraps the main EasyPG function that will ask for a password. It temporarily removes the environment variable that EasyPG looks for to connect to the GPG agent, and therefore EasyPG asks the user for the password as if there were no agent running.</p>

<p>Let's analyze the different parts of that advice function:</p>
<ul>
  <li>All advice starts with a "defadvice" definition.</li>
  <li>"epg--start" is the name of the original function I'm wrapping.</li>
  <li>"around" is indicating that I'm specifying code to run both before and after the function I'm wrapping (other options would include "before" and "after")</li>
  <li>The word "disable" means that the advice is initially turned off (you could say "activate" to have it immediately turned on, read the manual for more options here)</li>
  <li>Starting with the "let" function is the body of my custom function</li>
  <li>The "ad-do-it" line in the middle is the point in the function where the original function gets executed. (This would not be used in a "before" or "after" style function.)</li>
</ul>

<p>One more important thing to understand about advising a function is that you aren't creating a new function with a new name. You are adding data to the existing function definition. Wherever the original function gets called, your advice will be called along with it. However, advice does offer the convenience of turning on or off your changes. For the above example I added two user commands to turn on and off the GPG agent (bound to M-x epg-disable-agent and M-x epg-enable-agent):   </p>

<div class="pygments_murphy"><pre><span class="p">(</span><span class="n">defun</span> <span class="n">epg</span><span class="o">-</span><span class="n">disable</span><span class="o">-</span><span class="n">agent</span> <span class="p">()</span>
  <span class="s">&quot;Make EasyPG bypass any gpg-agent&quot;</span>
  <span class="p">(</span><span class="n">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="n">ad</span><span class="o">-</span><span class="n">enable</span><span class="o">-</span><span class="n">advice</span> <span class="s">&#39;epg--start &#39;</span><span class="n">around</span> <span class="s">&#39;advice-epg-disable-agent)</span>
  <span class="p">(</span><span class="n">ad</span><span class="o">-</span><span class="n">activate</span> <span class="s">&#39;epg--start)</span>
  <span class="p">(</span><span class="n">message</span> <span class="s">&quot;EasyPG gpg-agent bypassed&quot;</span><span class="p">))</span>

<span class="p">(</span><span class="n">defun</span> <span class="n">epg</span><span class="o">-</span><span class="n">enable</span><span class="o">-</span><span class="n">agent</span> <span class="p">()</span>
  <span class="s">&quot;Make EasyPG use a gpg-agent after having been disabled with epg-disable-agent&quot;</span>
  <span class="p">(</span><span class="n">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="n">ad</span><span class="o">-</span><span class="n">disable</span><span class="o">-</span><span class="n">advice</span> <span class="s">&#39;epg--start &#39;</span><span class="n">around</span> <span class="s">&#39;advice-epg-disable-agent)</span>
  <span class="p">(</span><span class="n">ad</span><span class="o">-</span><span class="n">activate</span> <span class="s">&#39;epg--start)</span>
  <span class="p">(</span><span class="n">message</span> <span class="s">&quot;EasyPG gpg-agent re-enabled&quot;</span><span class="p">))</span>
</pre></div>




<p>These functions use the (ad-enable-advice) and (ad-disable-advice) functions respectively. Whenever advice is switched on or off, a call to (ad-activate) must also be made on the function to update it.</p>

<p>The <a href="http://www.delorie.com/gnu/docs/elisp-manual-21/elisp_212.html">manual</a> goes into more depth about how to advice functions. Hopefully you got something useful out of this, I sure learned a lot in writing it.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Emacs ansi-term tricks</title>
      <link>http://www.enigmacurry.com/2008/12/26/emacs-ansi-term-tricks/</link>
      <pubDate>Fri, 26 Dec 2008 11:30:44 EST</pubDate>
      <category><![CDATA[emacs]]></category>
      <guid>http://www.enigmacurry.com/?p=296</guid>
      <description>Emacs ansi-term tricks</description>
      <content:encoded><![CDATA[
<p>Being on vacation is soo nice. With some of my free time I'm planning on revamping my emacs environment, so hopefully that means a few more articles showing up here on that topic.</p>

<p>I read <a href="http://jfm3-repl.blogspot.com/2008/11/how-i-use-emacs-ansi-term.html">some great tips</a> on ansi-term. Ansi-term is a terminal emulator written in emacs lisp that is as close to a real terminal as possible. That means you can run virtually all command line programs, even the ones that use ncurses like top or screen, all within emacs. You can still switch between line and char modes which means you can still edit the buffer as you could in a regular (emacs) shell too.</p>

<h3 class="intrablog">F2 Keybinding</h3>

<p>In the above mentioned article Joseph wrote a nice little bit of elisp to get to a running ansi-term efficiently, by hitting F2. The nice thing about it is that it <em><strong>does what I mean</strong></em>:</p>
<ol>
  <li>If I'm already in an ansi-term, but it's called "*ansi-term*" rename it.</li>
  <li>If I'm already in an ansi-term, but it's called something else, start a new ansi-term called "*ansi-term*"</li>
  <li>If I'm in another non-terminal buffer, switch to a buffer called "*ansi-term*" or create a new one if it doesn't exist</li>
</ol>

<p>There's one more catch though, as Joseph explains, an ansi-term can be considered "stopped" such that it is no longer running but the buffer still exists. In that case I don't want the third rule to switch me to a defunct terminal, so instead I want it to kill the buffer and create a new ansi-term. Here is my enhanced elisp:</p>

<div class="pygments_murphy"><pre><span class="p">(</span><span class="nb">require</span> <span class="ss">&#39;term</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">visit-ansi-term</span> <span class="p">()</span>
  <span class="s">&quot;If the current buffer is:</span>
<span class="s">     1) a running ansi-term named *ansi-term*, rename it.</span>
<span class="s">     2) a stopped ansi-term, kill it and create a new one.</span>
<span class="s">     3) a non ansi-term, go to an already running ansi-term</span>
<span class="s">        or start a new one while killing a defunt one&quot;</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">is-term</span> <span class="p">(</span><span class="nb">string=</span> <span class="s">&quot;term-mode&quot;</span> <span class="nv">major-mode</span><span class="p">))</span>
        <span class="p">(</span><span class="nv">is-running</span> <span class="p">(</span><span class="nv">term-check-proc</span> <span class="p">(</span><span class="nv">buffer-name</span><span class="p">)))</span>
        <span class="p">(</span><span class="nv">term-cmd</span> <span class="s">&quot;/bin/bash&quot;</span><span class="p">)</span>
        <span class="p">(</span><span class="nv">anon-term</span> <span class="p">(</span><span class="nv">get-buffer</span> <span class="s">&quot;*ansi-term*&quot;</span><span class="p">)))</span>
    <span class="p">(</span><span class="k">if</span> <span class="nv">is-term</span>
        <span class="p">(</span><span class="k">if</span> <span class="nv">is-running</span>
            <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nb">string=</span> <span class="s">&quot;*ansi-term*&quot;</span> <span class="p">(</span><span class="nv">buffer-name</span><span class="p">))</span>
                <span class="p">(</span><span class="nv">call-interactively</span> <span class="ss">&#39;rename-buffer</span><span class="p">)</span>
              <span class="p">(</span><span class="k">if</span> <span class="nv">anon-term</span>
                  <span class="p">(</span><span class="nv">switch-to-buffer</span> <span class="s">&quot;*ansi-term*&quot;</span><span class="p">)</span>
                <span class="p">(</span><span class="nv">ansi-term</span> <span class="nv">term-cmd</span><span class="p">)))</span>
          <span class="p">(</span><span class="nv">kill-buffer</span> <span class="p">(</span><span class="nv">buffer-name</span><span class="p">))</span>
          <span class="p">(</span><span class="nv">ansi-term</span> <span class="nv">term-cmd</span><span class="p">))</span>
      <span class="p">(</span><span class="k">if</span> <span class="nv">anon-term</span>
          <span class="p">(</span><span class="k">if</span> <span class="p">(</span><span class="nv">term-check-proc</span> <span class="s">&quot;*ansi-term*&quot;</span><span class="p">)</span>
              <span class="p">(</span><span class="nv">switch-to-buffer</span> <span class="s">&quot;*ansi-term*&quot;</span><span class="p">)</span>
            <span class="p">(</span><span class="nv">kill-buffer</span> <span class="s">&quot;*ansi-term*&quot;</span><span class="p">)</span>
            <span class="p">(</span><span class="nv">ansi-term</span> <span class="nv">term-cmd</span><span class="p">))</span>
        <span class="p">(</span><span class="nv">ansi-term</span> <span class="nv">term-cmd</span><span class="p">)))))</span>
<span class="p">(</span><span class="nv">global-set-key</span> <span class="p">(</span><span class="nv">kbd</span> <span class="s">&quot;&lt;f2&gt;&quot;</span><span class="p">)</span> <span class="ss">&#39;visit-ansi-term</span><span class="p">)</span>
</pre></div>




<h3 class="intrablog">TRAMP Integration</h3>
<a href="http://www.emacswiki.org/emacs/AnsiTermHints#toc4">This</a> is cool.

<p>Put the following inside of your .bash_profile on any computer that you ssh into frequently:</p>


<div class="pygments_murphy"><pre><span class="c">#Emacs ansi-term directory tracking</span>
<span class="c"># track directory, username, and cwd for remote logons</span>
<span class="k">if</span> <span class="o">[</span> <span class="nv">$TERM</span> <span class="o">=</span> eterm-color <span class="o">]</span>; <span class="k">then</span>
<span class="k">    function </span>eterm-set-cwd <span class="o">{</span>
        <span class="nv">$@</span>
        <span class="nb">echo</span> -e <span class="s2">&quot;\033AnSiTc&quot;</span> <span class="k">$(</span><span class="nb">pwd</span><span class="k">)</span>
    <span class="o">}</span>
    
    <span class="c"># set hostname, user, and cwd</span>
    <span class="k">function </span>eterm-reset <span class="o">{</span>
        <span class="nb">echo</span> -e <span class="s2">&quot;\033AnSiTu&quot;</span> <span class="k">$(</span>whoami<span class="k">)</span>
        <span class="nb">echo</span> -e <span class="s2">&quot;\033AnSiTc&quot;</span> <span class="k">$(</span><span class="nb">pwd</span><span class="k">)</span>
        <span class="nb">echo</span> -e <span class="s2">&quot;\033AnSiTh&quot;</span> <span class="k">$(</span>hostname<span class="k">)</span>
    <span class="o">}</span>
    
    <span class="k">for </span>temp in <span class="nb">cd pushd popd</span>; <span class="k">do</span>
<span class="k">        </span><span class="nb">alias</span> <span class="nv">$temp</span><span class="o">=</span><span class="s2">&quot;eterm-set-cwd $temp&quot;</span>
    <span class="k">done</span>
    
    <span class="c"># set hostname, user, and cwd now</span>
    eterm-reset
<span class="k">fi</span>
</pre></div>




<p>Now when you ssh into a machine from within ansi-term and open a file with C-x C-f you'll be loading a file via TRAMP from the current working directory <em>on the remote machine</em>. Amazingly cool.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Wrangling my finances</title>
      <link>http://www.enigmacurry.com/2008/10/21/wrangling-my-finances/</link>
      <pubDate>Tue, 21 Oct 2008 12:42:55 EDT</pubDate>
      <category><![CDATA[cool stuff]]></category>
      <category><![CDATA[emacs]]></category>
      <category><![CDATA[economics]]></category>
      <guid>http://www.enigmacurry.com/?p=177</guid>
      <description>Wrangling my finances</description>
      <content:encoded><![CDATA[
<p>I've gotten better at thinking about my finances over the years but I've never had anything better than a mental budget. I've never actually written anything down on paper. I've got a brand new job so I figure I've got a clean slate. Starting right now, I pledge to myself to keep a balanced checkbook at all times and to do monthly reviews of my finances looking for things to cut out of my budget.</p>

<p>Fiscal Conscience: Ha! How many times have you said that?<br/>
Me: Dozens of times!<br/>
Fiscal Conscience: And did you ever actually do it?<br/>
Me: No, but this time it will be different!<br/>
Fiscal Conscience: You're going to have do to better than that!<br/>
Me: Fine, I'll show you.<br/></p>

<p>GnuCash is a wonderful piece of open-source accounting software. I have used it myself, dozens of times. But as it happens I inevitably stop using it. Not because the software is flawed per se, it does everything a good accounting application should do:</p>
<ul>
	<li>Use Double-Entry accounting</li>
	<li>Support multiple currencies</li>
	<li>OFX import from online banking sites</li>
	<li>etc</li>
</ul>

<p>The only thing they get wrong is the fundamental design choice they made when developing the application: they made it a GUI. Sure, GUIs are great, but in my opinion GUIs should be interfaces to a service oriented application rather than the application itself. Unless I'm sitting at my desk at home I can't use my application. I don't consider remote desktops a reasonable response to this problem due to the huge network latency issues as well as firewall problems.</p>

<p>I want to be able to record my transactions from anywhere. At home at my desk, at work at my desk, on my N800 when traveling, or on my phone when running around. With an application fundamentally written as a GUI this is essentially an insurmountable problem. An application written as a service can do all of these things quite easily with minimal amounts of programming.</p>

<p>Enter <a href="http://www.newartisans.com/software/ledger.html">Ledger</a>.</p>

<p>Ledger does not keep track of your accounts. <strong>You</strong> keep track of your accounts in a plain text file and Ledger helps you understand them better. I can update my checkbook register from any text editor, anywhere I am. Most often this is Emacs through SSH on my home computer. Because of the triviality of the file format (being plain text) I can write a simple application that takes text messages from my phone and adds them to the register automatically.</p>

<img src="/blog-post-images/ledgerscreenshot.png" alt="" title="ledgerscreenshot" align="center" />

<p>But what about all my automatic payments?</p>

<p>I have most of my monthly payments automatically debited from my account. This is nice since I don't have to spend the time submitting payments to X number of companies each month, but is a nightmare when it comes time to balancing my checkbook. What I have done in the past is to just import an OFX file from my bank directly into GnuCash. This works great until you realize that something is wrong with the import and your checkbook is no longer balancing correctly. For this reason alone I prefer to record each transaction I make by hand. My money is my responsibility after all.</p>

<p>So, I wanted to be instantly notified of any debit on my checking account as soon as it happens. This gives me the following:</p>
<ul>
	<li>A text message to my phone describing the time, place and amount of the transaction</li>
	<li>The total balance of my account</li>
	<li>A way to constantly keep an eye on how I'm spending my money without the hassle of (remembering to) signing into my bank account</li>
	<li>A reminder to balance my checkbook. (tells me when my actual checking balance has been out of sync with ledger for over 48 hours.)</li>
</ul>

<p>The central peice to this process is getting the transaction data from my bank account. My bank offers online banking but it does not offer an easy way to download my transactions. Sure it supports Quicken and MS Money exports, but its all protected behind a password protected javascript-enabled website. I wanted to use the wonderful <a href="http://wwwsearch.sourceforge.net/mechanize/">mechanize</a> library for python. However, it doesn't support javascript.</p>

<p>Enter <a href="http://selenium-rc.openqa.org/">Selenium RC</a>.</p>

<p>Selenium RC is an application that can remote control a real web browser and submit and receive data. I run selenium which launches Firefox in a headless X-server (Xvfb) and continuously refreshes my online banking site and parses out my account activity. This is probably a bit memory intensive to always keep a browser open for this specific purpose. I may want to experiment with python-spidermonkey in the future and go back to using mechanize, but I think there's a lot of glue missing in that solution whereas Selenium RC works perfectly right now!</p>

<p>No code to share at the moment, it's all a giant hack. If a similar setup appeals to someone out there, let me know and I'll think about releasing something.</p>]]></content:encoded>
    </item>
    <item>
      <title>Shortened URLs in Emacs using is.gd (like tinyurl)</title>
      <link>http://www.enigmacurry.com/2008/09/15/shortened-urls-in-emacs-using-isgd-like-tinyurl/</link>
      <pubDate>Mon, 15 Sep 2008 11:11:20 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[emacs]]></category>
      <guid>http://www.enigmacurry.com/?p=156</guid>
      <description>Shortened URLs in Emacs using is.gd (like tinyurl)</description>
      <content:encoded><![CDATA[
<p>I've casually been teaching myself emacs lisp lately. Today I wrote a utility that shortens long urls within regions using the <a href="http://is.gd">http://is.gd</a> URL shortening service. There's plenty of <a href="http://www.emacswiki.org/cgi-bin/wiki/tinyurl.el">existing code</a> out there that is more lisp like, but this is supposed to be a learning experience for me so I did it myself. I like python and so I used python for most of the heavy lifting.</p>

<p>I created a directory to hold all of my emacs specific python functions: ~/.emacs.d/ryan-pymacs-extensions</p>

<p>I wrote the following python function, shorten_url.py in that directory:</p>


<div class="pygments_murphy"><pre><span class="err">!</span><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">env</span> <span class="n">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;Mon Sep 15 12:27:14 2008&quot;</span>

<span class="kn">import</span> <span class="nn">doctest</span>
<span class="kn">import</span> <span class="nn">urllib2</span>
<span class="kn">import</span> <span class="nn">re</span>

<span class="k">def</span> <span class="nf">shorten_with_is_gd</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Shorten a URL with is.gd</span>

<span class="sd">    &gt;&gt;&gt; shorten_with_is_gd(&#39;http://www.enigmacurry.com&#39;)</span>
<span class="sd">    &#39;http://is.gd/FFP&#39;</span>

<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">u</span> <span class="o">=</span> <span class="n">urllib2</span><span class="o">.</span><span class="n">urlopen</span><span class="p">(</span><span class="s">&quot;http://is.gd/api.php?longurl=&quot;</span><span class="o">+</span><span class="n">url</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">u</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>

<span class="k">def</span> <span class="nf">shorten_in_text</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
    <span class="sd">&quot;&quot;&quot;Shorten all the urls found inside some text</span>

<span class="sd">    &gt;&gt;&gt; shorten_in_text(&#39;Hi from http://www.enigmacurry.com&#39;)</span>
<span class="sd">    &#39;Hi from http://is.gd/FFP&#39;</span>
<span class="sd">    </span>
<span class="sd">    &quot;&quot;&quot;</span>
    <span class="n">replacements</span> <span class="o">=</span> <span class="p">{}</span> <span class="c">#URL -&gt; is.gd URL</span>
    <span class="c">#Only check for urls that start with &quot;http://&quot; for now</span>
    <span class="k">for</span> <span class="n">m</span> <span class="ow">in</span> <span class="n">re</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="s">&quot;http://[^ </span><span class="se">\n\r</span><span class="s">]*&quot;</span><span class="p">,</span> <span class="n">text</span><span class="p">):</span>
        <span class="k">try</span><span class="p">:</span>
            <span class="n">replacements</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="o">=</span> <span class="n">shorten_with_is_gd</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="k">except</span><span class="p">:</span>
            <span class="n">replacements</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="o">=</span> <span class="n">m</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
    <span class="k">for</span> <span class="n">url</span><span class="p">,</span><span class="n">replacement</span> <span class="ow">in</span> <span class="n">replacements</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
        <span class="n">text</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">replacement</span><span class="p">)</span>
    <span class="k">return</span> <span class="n">text</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">doctest</span><span class="o">.</span><span class="n">testmod</span><span class="p">(</span><span class="n">verbose</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
</pre></div>




<p>and the following lisp makes "M-x shorten-url" do the rest of the replacement work:</p>


<div class="pygments_murphy"><pre><span class="c1">;add ~/.emacs.d/ryan-python-extensions to python path</span>
<span class="p">(</span><span class="nv">pymacs-exec</span> <span class="s">&quot;import sys, os&quot;</span><span class="p">)</span>
<span class="p">(</span><span class="nv">pymacs-exec</span> <span class="s">&quot;sys.path.append(os.path.join(os.path.expanduser(&#39;~&#39;),&#39;.emacs.d&#39;,&#39;ryan-pymacs-extensions&#39;))&quot;</span><span class="p">)</span>

<span class="c1">;;Shorten URLs with is.gd</span>
<span class="p">(</span><span class="nv">pymacs-exec</span> <span class="s">&quot;import shorten_url&quot;</span><span class="p">)</span>
<span class="p">(</span><span class="nb">defun</span> <span class="nv">shorten-url</span> <span class="p">(</span><span class="nv">start</span> <span class="nv">end</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">interactive</span> <span class="s">&quot;r&quot;</span><span class="p">)</span>
  <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">region</span> <span class="p">(</span><span class="nv">buffer-substring</span> <span class="nv">start</span> <span class="nv">end</span><span class="p">)))</span>
    <span class="p">(</span><span class="k">let</span> <span class="p">((</span><span class="nv">rt</span> <span class="p">(</span><span class="nv">pymacs-eval</span> <span class="p">(</span><span class="nb">format</span> <span class="s">&quot;shorten_url.shorten_in_text(&#39;&#39;&#39;%s&#39;&#39;&#39;)&quot;</span> <span class="nv">region</span><span class="p">))))</span>
      <span class="p">(</span><span class="nv">kill-region</span> <span class="nv">start</span> <span class="nv">end</span><span class="p">)</span>
      <span class="p">(</span><span class="nv">insert</span> <span class="nv">rt</span><span class="p">)</span>
      <span class="p">)</span>
  <span class="p">))</span>
</pre></div>



]]></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>Emacs as a powerful Python IDE</title>
      <link>http://www.enigmacurry.com/2008/05/09/emacs-as-a-powerful-python-ide/</link>
      <pubDate>Fri, 09 May 2008 15:27:37 EDT</pubDate>
      <category><![CDATA[python]]></category>
      <category><![CDATA[enigma curry]]></category>
      <category><![CDATA[emacs]]></category>
      <guid>http://www.enigmacurry.com/?p=146</guid>
      <description>Emacs as a powerful Python IDE</description>
      <content:encoded><![CDATA[
<p><small><b>Update 01/2009: this post is still valid, but see updated <a href="/2009/01/19/my-emacs-config-on-github/">installation instructions here.</a></b></small></p>

<p>Last night at the <a href="http://www.utahpython.org">Python user group</a> I gave a short demo on using Emacs as a Python editor/IDE. My macbook pro refused to display on the projector so I thought my demo was going to be a 'no go'. Thankfully, <a href="http://blog.sontek.net/">sontek</a> allowed me to use his Linux laptop. I hurriedly copied over my emacs environment, installed a few packages and was able to present after all. I think the demo went fairly well even though I think it was a bit hurried and I forgot to cover a few things, I think I was pretty nervous at the same time because of the fact that the mac didn't work and got me flustered. Oh well, I think people enjoyed it.</p>

<h3 class="intrablog">My Emacs Environment</h3>

<p>Below are the Emacs features most applicable to Python development:</p>

<ul>
  <li><a href="http://rope.sourceforge.net/ropemacs.html">Rope and Ropemacs</a>
    Rope is a general (non-emacs specific) Python IDE library. It has awesome support for multiple refactoring methods and code introspection. Inside Emacs, this gives us:
    <ul>
      <li>Full (working!!) code-completion support of modules, classes, methods etc. (M-/ and M-?)</li>
      <li>Instant documentation for element under the cursor (C-c d)</li>
      <li>Jump to module/class/method definition of element under the cursor (C-c g). This works for any Python code it finds in your PYTHONPATH, including things from the stdlib.</li>
      <li>Refactoring of code (like rename -- C-c r r)</li>
      <li>List all occurences of of a name in your entire project</li>
      <li> <a href="http://rope.sourceforge.net/ropemacs.html">and More.</a></li>
    </ul>
  </li>
  <li><a href="http://code.google.com/p/yasnippet/">YASnippet</a>
    YASnippet is a snippet tool like TextMate. You can expand user defined keywords into whole blocks of predefined code. This is especially useful for the usual boilerplate that would go into a python file like 

<pre>#!/usr/bin/env python</pre> 
and 
<pre>if __name__ == '__main__':</pre>

<p> Granted, Python doesn't require much boilerplate, and therefore this package is much more suited to languages like Java, but I bring it up because I think its cool and if you get into the habit of using it, then a few keystrokes saved here and there will add up over time.</p>
  </li>
  <li>Subversion support with <a href="http://www.xsteve.at/prg/emacs/psvn.el">psvn.el</a>
    Psvn is a comprehensive subversion client for Emacs. It integrates well with ediff mode so you can use it to check changes between versions. It does all of the other boring subversion stuff well too.
  </li>
  <li><a href="http://www.cua.dk/ido.html">Ido-mode</a> for buffer switching and file opening.
    Emacs, to the uninitiated, can be confusing because by default there is only one view into a single file at a time. How does one get to another file? Instead of cluttering the interface with GUIness and making the user click somewhere (and thereby forcing the user to waste their time by moving their hand off of the keyboard), Emacs gives powerful ways to switch between files. Ido-mode is one of these useful ways -- it makes a list of open files starting with the most frequently visted files and widdles this list down as you type part of the filename. You can have dozens of files open and only be a few keystrokes away from any one of them.
</ul>


<p>A lot of people, for whatever reason, don't feel that Emacs is an IDE at all. I don't personally care what you define it as -- the fact remains -- Emacs is a powerful Python environment and despite being over 32 years old has proven to be just as modern as any IDE today, and remains THE most configurable editor (operating system?) ever.</p>

<p>I've <a href="/blog-post-files/Ryan-McGuire-Emacs-Environment-05-09-2008.tar.gz">tarred up my Emacs environment for general consumption</a>. Instructions:</p>
<ul>
  <li>Install <a href="http://pymacs.progiciels-bpi.ca/">Pymacs</a></li>
  <li>Install <a href="http://rope.sourceforge.net/">Rope</a> and <a href="http://rope.sourceforge.net/ropemacs.html">Ropemacs</a></li>
  <li>BTW, those three packages should be the only packages other than Emacs you'll need. Everything else is self contained.
  <li>Extract the tarball to your home directory. This creates a directory called ryan-emacs-env.</li>
  <li>Rename "ryan-emacs-env" to ".emacs.d"</li>
  <li>Symlink my dot-emacs file to your .emacs. Run "ln -s .emacs.d/dot-emacs .emacs". </li>
  <li>If you also want to do Java development run "tar xfvz jde-2.3.5.1.tar.gz". I leave it tarred because you don't need to pollute your environment if you're not going to use Java. (Also for whatever reason, jde doesn't like to be stuck in my subversion repository so I just leave it tarred up and untar on every machine I check it out on.)</li>
</ul>

<p>Extra tips:</p>
<ul>
<li>Put your .emacs.d directory under version control. Never rely on your distros emacs packages, install all future elisp files yourself in your .emacs.d file and commit to your repository often. This way you've got an environment that is easily transportable and synchronizable across multiple machines. This is the major reason why my emacs environment was so fast to trasnfer from my macbook pro to sontek's laptop during the demo.</li>
<li>Speaking of sontek, he brought up an excellent point in #utahpython the other day, he's not going to be using my emacs environment except for reference, instead he's starting with a clean slate. This is by far the best and most prudent thing to do. My emacs environment is a culmination of several years of plugging in and deleting various packages and writing various snippets of elisp. Your needs are always going to be different than mine and you are also going to be better off by educating yourself along the way by creating your own.</li>
</ul>

<p>Some more fun Emacs evangelism:</p>
<ul>
 <li>a <a href="http://platypope.org/yada/emacs-demo/">fascinating screencast of Emacs</a> in the role of Ruby editor (many tips here apply to Python too)</li>
 <li>Emacs blogs I read:
   <ul>
     <li><a href="http://emacslife.blogspot.com/">Emacs life</a></li>
     <li><a href="http://trey-jackson.blogspot.com/">Life is too short for bad code</a></li>
     <li><a href="http://emacs.wordpress.com/">Minor Emacs Wizardry</a></li>
     <li><a href="http://www.emacsblog.org/">M-x all-things-emacs</a></li>
     <li><a href="http://platypope.org/blog/">Platypope.org</a></li>
     <li>Know of any other good ones? Let me know.</li>
   </ul>
</ul>
]]></content:encoded>
    </item>
  </channel>
</rss>

