<?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>Thu, 07 Jan 2010 01:58:15 GMT</pubDate>
    <generator>Blogofile</generator>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Initial Nexus One Impressions</title>
      <link>http://www.enigmacurry.com/2010/01/06/initial-nexus-one-impressions</link>
      <pubDate>Wed, 06 Jan 2010 18:39:00 EST</pubDate>
      <category><![CDATA[Android]]></category>
      <guid>http://www.enigmacurry.com/2010/01/06/initial-nexus-one-impressions</guid>
      <description>Initial Nexus One Impressions</description>
      <content:encoded><![CDATA[<p>Just got my Nexus One delivered :)
</p>
<p>Although I had a company issued Blackberry (7100t) several years ago, I've never owned a smart phone of my own. I've certainly watched the technology progress over the years, but for the last several of those years I've been content to own a generic 3g slider phone (Samsung A737) and just tethering it to my Nokia N800.
</p>
<p>Recently, smartphones have seemingly gotten a lot more powerful and I decided it was time for me to get one. Having loved my N800, I certainly had my eyes on the N900, not only because it adds a phone feature, but maemo 5 looks fscking awesome. However, I did my due dilligence and researched the other options available, and here are my thoughts on what's out there right now:
</p>
<ul>
 <li><p>iPhone 3Gs: I've played with it several times at the Apple store, and held several owned by friends. It runs on fantastic hardware and even better core software. The iPhone is seriously stable and runs smoothly as far as I can tell. It only has one problem: Apple designed the software to be completely locked down. As a software developer (who wants to program for whatever phone he gets) I can't bring myself to become a slave to Apple, not being able to develop on anything but a mac, using a language that seemingly is only used to build Apple software, having to pay a large license fee to put applications on the only available method of distributing applications (THE app store), and to top all that off, I have absolutely no guarantee whatsoever that Apple will even accept my application, let alone in a timely fashion. No thanks.
</p>

 </li>

 <li><p>Nokia N900: Oh, this phone has everything I want. Everything the N800 had and more. Completely open-source, completely unlocked device, surrounded by a (small by comparison) community that <strong>wants</strong> me to hack this device. Yea, this is my kind of phone. The idealist in me knows that this is the best phone on the market right now, and if adopted en masse, would shake the telecom industry to its core. A powerful phone like this, giving me as much freedom as it does, has the potential to force the telecom providers to compete solely on terms of network quality as opposed to competing over who has the coolest (locked down) phone. However, like with Betamax, there's more to winning than just superior technology. Nokia just doesn't have that something. This phone will serve geeks and enthusiasts well, but it just doesn't have the character to be adopted widely, and as a developer, I'd like to see the programs I write, as well as the skills that I will develop, still have relevance several years from now.
</p>

 </li>

 <li><p>Android: Android is this happy medium between the two. The Android platform is open source. The phones... well, not so much. While they all run more or less the same open source android OS, they are still chained to the whims and pleasure of the manufacturer and telecom carrier, not the consumer. The recent Motorola Cliq is a perfect example of this. This is a new phone, having only been released since last November. But already the OS is quite outdated, running android 1.5, it's now three versions behind the latest that the Nexus One is running (2.1). I certainly understand that there are complications in upgrading the device, but it's the fact that Motorola/Tmobile has delivered a device that although is running an open source OS, is completely locked down disallowing the user to upgrade the phone himself. Ingenious hackers have <a href="http://www.redmondpie.com/how-to-root-motorola-cliq-for-full-android-access-9140260/">rooted the device</a> (without motorola's help mind you) but there is still trouble in installing new OS images. The Motorola Cliq is NOT an open source friendly phone and is defeinitly not the phone for me.
</p>

 </li>
</ul>
<p>So a few weeks ago I was reading Android developer docs and was becoming really impressed with the platform. Even though it's all Java based, and not my beloved Python, at least it wasn't Objective C. And even though there are some closed source google APIs included, the great majority of android is open source. I was starting to the get feeling that this was a platform I could roll with. But the most modern phone available on a carrier I can afford (have you seen the prices for family plans on Verizon, sheesh) was the Motorola Cliq, and that phone deeply depresses me. So, did I want one of the older Android phones, the MyTouch or the G1? Hell no, I wanted something at least as powerful as the droid, if not as powerful as the N900 itself. Ah, but then all the rumors of the Nexus One starting cropping up all over the web.
</p>
<ul>
 <li>
     Nexus One: A brand new, modern android phone, more powerful than the droid, hell more powerful than the N900 (at least on paper), not running any proprietary Motorola firmware, made by google who has an interest in making this the flagship android offering and playing nicely with developers, they made it <a href="http://android.modaco.com/content/google-nexus-one-nexusone-modaco-com/299078/how-to-unlock-the-bootloader-on-your-nexus-one/">easy to unlock the bootlader</a> (literally just reboot holding down the trackball and entering a special command).. the list goes on. <strong>This phone is still no N900, but this just might be the first mainstream, truley open-source phone, that has the gumption to compete directly with the iPhone.</strong>
 </li>
</ul>
<p>So I bought one :)
</p>
<p>Here's my initial impressions:
</p>
<ul>
 <li><p>Fedex is soo good at what they do. I set firefox to continuously reload <a href="http://www.google.com/phone">http://www.google.com/phone</a> during the Nexus One press launch, and as soon as the page went live I purchased the phone. Google paid the shipping and HTC sent it Fedex overnight. Less than 24 hours later, it was in my mailbox. Nice!
</p>

 </li>

 <li><p>It's going to take me a while to get used to the keyboard. I have zero experience with touchscreen keyboards without the aid of a stylus.
</p>

 </li>

 <li><p>Dictation works pretty well, kinda alleviates the problem above, although I probably would feel awkward using it in public.
</p>

 </li>

 <li><p>The software keys at the bottom of the phone are very finicky. Although having used the phone for a few hours now, I think I got the handle of them now.
</p>

 </li>

 <li><p>Navigation is fantastic. The GPS lockon was instantaneous, using dicatation to give the desired address worked flawlessly, the turn by turn speech is understandable, and the map displayed is updated quickly (even over EDGE) and looks great.
</p>

 </li>

 <li><p>Just got Sipdroid setup and I can make VoIP calls for practically nothing :) (I have only tested it on WiFi so far, don't have 3G yet)
</p>

 </li>

 <li><p>I can't connect to my home router that's only 8 feet away, even though it sees it, no idea why. I'm using WPA2 PSK AES, maybe it doesn't like AES? Can connect to the neighbors unprotected wifi ("linksys") no problem though ;)
</p>

 </li>

 <li><p>The web browser works great and is speedy even on EDGE. I think something was terribly wrong in <a href="http://www.engadget.com/2010/01/04/nexus-one-review/">the Edgadget browser test</a> because when I tried the same test (on WiFi), I got the page to load up at the exact same time the iphone did in the video, and seriously, why wouldn't it? Both the iphone and the Nexus One use webkit.
</p>

 </li>
</ul>
<p>I'll update this list if anything else hits me.
</p>]]></content:encoded>
    </item>
    <item>
      <title>Writing an OpenOffice.org Calc extension in Python</title>
      <link>http://www.enigmacurry.com/2009/12/13/writing-an-openoffice.org-calc-extension-in-python</link>
      <pubDate>Sun, 13 Dec 2009 10:08:00 EST</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[OpenOffice.org]]></category>
      <guid>http://www.enigmacurry.com/2009/12/13/writing-an-openoffice.org-calc-extension-in-python</guid>
      <description>Writing an OpenOffice.org Calc extension in Python</description>
      <content:encoded><![CDATA[<p>A very well organized group of thugs steals my money every day. I'm getting really tired of it, but I found a way to save at least some of my money so they don't steal nearly as much of it, nearly as often. For whatever reason, this gang hasn't devised a way to steal gold and silver nearly as efficiently as these little green pieces of paper that they call money. So I buy gold and silver whenever I can as a hedge against 'inflation' (which is really just their gang-speak for the wholesale-theft of my money.)
</p>
<p>I want to keep track of how much gold and silver I've bought, when I bought it, and inevitably I'll still want to know how many green pieces of paper I could theoretically trade it all in for.
</p>
<p>The easiest way to track all this information was to create a spreadsheet in OpenOffice.org's Calc. I created a sheet for gold purchases and another sheet for silver purchases. Everytime I make a purchase, I record the number of ounces, what form it is in (coins, bars, junk etc), who I bought it from, when I bought it, and the price I paid in FRNs (Federal Reserve Notes, aka green pieces of paper.) On another sheet I total the number of ounces I own and multiply it by the current spot price for the metal, which gives me the current price I could get if I sold it for FRNs. When tallying this total, I reference a special cell on the sheet, one that has the current spot price for gold, and another for silver.
</p>
<p>But checking the spot price myself and manually updating those cells was just too tedious for my programmer's heart. I wanted OpenOffice.org to automatically retrieve this information for me. So, I started researching OpenOffice.org extensions (plugins).
</p>
<p>Turns out, OpenOffice.org extensions can be written in my favorite programming language, Python (yea!), so I wrote the following extension a few weekends ago. It's <a href="http://github.com/EnigmaCurry/SpotMetal">on github</a> and can be downloaded with git:
</p>
<div class="highlight"><pre>  git clone git://github.com/EnigmaCurry/SpotMetal.git
</pre></div>

<p>If you just want the pre-compiled extension, it can be downloaded here locally:
</p>
<p><a href="/blog-post-files/SpotMetal-0.1.oxt">SpotMetal-0.1.oxt</a>
</p>
<p>You install it inside OpenOffice.org by going to <code>Tools -&gt; Extension Manager</code> and clicking on <code>Add</code> and browsing to the <code>SpotMetal-0.1.oxt</code> file you downloaded or built yourself.
</p>
<p>Once you have it installed, you now have a new Calc function available called <code>SPOTMETAL</code> which takes two arguments:
</p>
<ul>
 <li>
     <em>metal</em> - Which metal you want to look up. Can be one of <code>"gold", "silver", "platinum",</code> or <code>"palladium"</code>
 </li>

 <li>
     <em>bidAsk</em> - Whether you want the bid or the ask price. Can be either <code>"bid"</code> or <code>"ask"</code>.
 </li>
</ul>
<p>The price will automatically be refreshed every 5 minutes by default, but you can also force a refresh with the Calc function called <code>SPOTMETALREFRESH</code>.
</p>
<p>Here's an <a href="/blog-post-files/MetalTrackerExample.ods">example OpenOffice.org spreadhseet</a> that shows how you might track your own precious metal investment portfolio. The big button labeled "Refresh Spot Price" does what it says it does, but requires a bit more boiler-plate code in order for it to actually display on screen. In OpenOffice.org, you can see another macro called doReCalculate:
</p>
<ul>
 <li>
     <code>Tools-&gt;Macros-&gt;Organize Macros-&gt;OpenOffice.org Basic</code> 
 </li>

 <li>
     <code>MetalTrackerExample.ods-&gt;Standard-&gt;SpotMetal-&gt;doReCalculate</code>. 
 </li>
</ul>
<p>This extra macro is necessary to actually force the spreadsheet to request new data from the extension when you click the "Refresh Spot Price" button.
</p>
<p>While this extension might be of use to you if you also invest in precious metals, I guess the main reason I posted this is because it took a good deal of time researching how to write a Python extension for OpenOffice.org. Check out <a href="http://github.com/EnigmaCurry/SpotMetal">the source code on github</a> if you're looking to write your own extension, it's got it's own Makefile and hopefully it's documented well enough for it be useful for someone in the future.
</p>]]></content:encoded>
    </item>
    <item>
      <title>EnigmaCurry.com now powered by Blogofile</title>
      <link>http://www.enigmacurry.com/2009/07/20/enigmacurry.com-now-powered-by-blogofile</link>
      <pubDate>Mon, 20 Jul 2009 22:04:00 EDT</pubDate>
      <category><![CDATA[Blogofile]]></category>
      <category><![CDATA[EnigmaCurry.com]]></category>
      <guid>http://www.enigmacurry.com/?p=447</guid>
      <description>EnigmaCurry.com now powered by Blogofile</description>
      <content:encoded><![CDATA[<p>Phew! 
</p>
<p>I've just finished porting this entire site over to my new blog engine, <a href="http://www.blogofile.com">Blogofile</a>. Blogofile is something I've been working on for the last several months, and really it's been pretty much complete for the last two of those months; it turns out that transferring the 100+ posts that I've made on this blog since 2005, first using TikiWiki, then Wordpress (using a myriad of different plugins over the years) was a much larger task than writing Blogofile itself. Or, at least writing Blogofile was a lot more fun, which is why it probably took me so long to do the relatively mundane task of porting EnigmaCurry to the new platform.
</p>
<p>Blogofile is best described as a Blog Compiler -- just as a programmer's compiler takes source code and spits out a running program, a blog compiler takes a special blog source code language and spits out raw HTML, the native format of all blogs everywhere. What this means is that any webserver can host the Blogofile based blog, without having to install any special software, not even Blogofile, it's just HTML. You can run Blogofile on any computer that has Python installed, upload the HTML it generates to your webserver, and your webserver remains lean and fast.
</p>
<p>You can read more of the great features of Blogofile <a href="http://www.blogofile.com">on it's own site</a>.
</p>
<p>One of the biggest motivators in my finishing up moving EnigmaCurry.com over to Blogofile is because, quite frankly, MySQL 5.x blows chunks. It consumes ridiculous amounts of RAM for my pitifully small wordpress database, and when it eventually overwhelms my VPS and forces a restart, the tables are corrupted, especially the mysql user table which requires running "mysqld --skip-grant-tables" in order to get running again just so I can get in to repair the damage. I've seen this happen on two different (but pretty much stock configured) Ubuntu 9.04 servers, so I know it's not an isolated case. I've pledged to myself to never use MySQL in future projects. Do yourself a favor:
</p>
<div class="highlight"><pre>sudo apt-get remove mysql-server-5.0
</pre></div>

<p>Please don't hesitate to <a href="http://mailhide.recaptcha.net/d?k=01VHGYFI7WE9jB_dHebD-0JQ==&amp;c=3qCKNvkRgZtCa5B5PJcptJVgaDI5-xiMjUjHgQi3vIw=">let me know</a> if you see something awry with the site, there's bound to still be a few things missing/corrupted from the transfer.
</p>]]></content:encoded>
    </item>
    <item>
      <title>Ambient Composition 1</title>
      <link>http://www.enigmacurry.com/2009/05/31/ambient-composition-1/</link>
      <pubDate>Sun, 31 May 2009 15:24:07 EDT</pubDate>
      <category><![CDATA[Music]]></category>
      <guid>http://www.enigmacurry.com/?p=446</guid>
      <description>Ambient Composition 1</description>
      <content:encoded><![CDATA[
<p>I've always wished that I was a musician, I love music. When I was young, my parents even paid for piano lessons, although I gave that up shortly after. Back then I saw it as tedious, and I never saw any real improvement.</p>

<p>I'm hoping to change direction. I seem to always have a tune inside my head and it needs to get out!</p>

<p>I recently bought a new computer powerful enough to run some pretty amazing software synthesizers, so I've started composing some music. Here's a pretty basic one I wrote today:</p>

<object type="application/x-shockwave-flash" data="/flash/mp3player.swf" id="audioplayer1" height="24" width="290"><param name="movie" value="/flash/mp3player.swf"><param name="FlashVars" value="playerID=1&amp;bg=0xf8f8f8&amp;leftbg=0xeeeeee&amp;lefticon=0x666666&amp;rightbg=0xcccccc&amp;rightbghover=0x999999&amp;righticon=0x666666&amp;righticonhover=0xffffff&amp;text=0x666666&amp;slider=0x666666&amp;track=0xFFFFFF&amp;border=0x666666&amp;loader=0x9FFFB8&amp;soundFile=http%3A%2F%2Fenigmacurryweb.s3.amazonaws.com%2FRyan_McGuire_-_Ambient_Composition_1_-_May_31_2009.mp3%3FAWSAccessKeyId%3D0JN1QB6N50D9MPHAQ8R2%26%23038%3B"><param name="quality" value="high"><param name="menu" value="false"><param name="bgcolor" value="#FFFFFF"></object><br/>
(press play or <a href="http://enigmacurryweb.s3.amazonaws.com/Ryan_McGuire_-_Ambient_Composition_1_-_May_31_2009.mp3?AWSAccessKeyId=0JN1QB6N50D9MPHAQ8R2&">right click here to download</a>)

<p>It's pretty ambient. This is for two reasons:</p>
<ol>
	<li>I actually <em>like</em> ambient music, eg. Harold Budd or The Dead Texan.</li>
	<li>It's got a low barrier to entry, nice long whole notes. :)</li>
</ol>

]]></content:encoded>
    </item>
    <item>
      <title>Distributing Jython Apps in a Single JAR file</title>
      <link>http://www.enigmacurry.com/2009/05/20/distributing-jython-apps-in-a-single-jar-file/</link>
      <pubDate>Wed, 20 May 2009 14:20:51 EDT</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Java]]></category>
      <guid>http://www.enigmacurry.com/?p=440</guid>
      <description>Distributing Jython Apps in a Single JAR file</description>
      <content:encoded><![CDATA[
<p>I've been writing a lot of one-off type applications at work lately, which is always kind of a joy for me because these sorts of applications don't need to be maintained or supported in any way, which means I can write them however I want.</p>

<p>So I write them in Python :)</p>

<p>Jython allows me to interface with all the plethora of Java libraries that we use at work, and it lets me program in a language that not only I can tolerate, but one that I respect and love.</p>

<p>But even though these are one-off applications, they still need to be easy to use, and in some cases I won't even be the one running the application. I want these applications to just work damnit.</p>

<p>So, packaging my Jython application into a single executable jar file that contains all of the third party dependancies inside is my goal. I want to send the user the jar file, have them double click on it, and have it immediately start running. It can't get a whole lot easier than that.</p>

<p>The <a href="http://wiki.python.org/jython/JythonFaq/DistributingJythonScripts">Jython wiki has a page</a> about doing something along these lines. The recipe there called the <a href="http://wiki.python.org/jython/JythonFaq/DistributingJythonScripts#UsingtheJarMethod">Jar Method</a> works quite well. The one drawback that it has is that all of the Java dependancies need to be exploded into the main jar root, which when you're dealing with dozens of jar dependancies, it can start to get tedious, messy, and in some cases will even violate the license of a particular library.</p>

<p><a href="http://one-jar.sourceforge.net/">One-Jar</a> is a special class loader that can load a jar file that is inside of another jar file, something that the regular class loader from Sun is incapable of doing. Using One-Jar lets my application reside inside of a jar file and contain all my dependancies as seperate jar files inside the main jar file.</p>

<p>I've created a sample project that shows how I normally create a new Jython project hosted inside a single jar file with One-Jar. You'll need the following tools to check out the project:</p>

<ul>
    <li>A Java SDK (tested with <a href="http://openjdk.java.net/">OpenJDK 1.6</a>)</li>
    <li><a href="http://ant.apache.org/">Apache Ant</a> (tested with version 1.7)</li>
    <li><a href="http://git-scm.com/">Git</a> (to checkout the project)</li>
</ul>
<p>Check out the project like so:</p>
<div class="highlight"><pre> git clone git://enigmacurry.com/single-jar-jython-example
</pre></div>

<p>Build the project:</p>
<div class="highlight"><pre><span class="nb">cd </span>single-jar-jython-example

ant
</pre></div>

<p> Run the example by double clicking it or via the command line:</p>
<div class="highlight"><pre> java -jar JythonExcelExample.jar
</pre></div>

<p>This is just a demonstration app, it doesn't do a whole lot, it outputs an excel file in the current directory listing some computer parts. The point of the application is to show how Jython can integrate with existing Java third-party libraries (in this case Apache POI.)</p>

<p>Instructions for basing your own application on this example are contained inside the README.txt file.</p>
]]></content:encoded>
    </item>
    <item>
      <title>Jython Shell Server -- Adding a REPL to any Java app</title>
      <link>http://www.enigmacurry.com/2009/03/01/jython-shell-server-adding-a-repl-to-any-java-app/</link>
      <pubDate>Sun, 01 Mar 2009 14:10:02 EST</pubDate>
      <category><![CDATA[Python]]></category>
      <category><![CDATA[Java]]></category>
      <guid>http://www.enigmacurry.com/?p=430</guid>
      <description>Jython Shell Server -- Adding a REPL to any Java app</description>
      <content:encoded><![CDATA[
<p>I love programming in Python. I get paid to write Java though. Due to <a href="/2007/04/20/python-vs-java/">Java's verboseness</a>, and lack of a REPL, this can be very frustrating for me. </p>

<p>In Python, the usual way I explore a new library or mock up a new idea is to immediately start coding in Python's interactive interpreter (or <a href="http://www.wikipedia.com/wiki/REPL">REPL</a>). This is often times more efficient than reading (let alone finding) the documentation for the library. I can quickly see if something is going to work before I code inside my larger application.</p>

<p>Java doesn't have an interactive interpreter.. but <a href="http://www.jython.org">Jython</a> does! However, setting up Jython, especially interfacing with an already large Java application, can be difficult. One such difficult situation I deal with at work is in Weblogic. With Weblogic, I deploy my application directly to a running Weblogic server, and I never get to see a console in this process, so how am I ever going to run a Jython interactive interpreter?</p>

<p>This morning I got bored and wrote up a quick solution: <a href="http://github.com/EnigmaCurry/jython-shell-server/tree">JythonShellServer</a>. JythonShellServer embeds into any Java application and starts a Telnet server that serves up Jython interactive shells. You can push any Java object that you want to manipulate into Jython's local environment. Run "telnet localhost 7000" and you can use Python code to explore your entire application's running environment.</p>

<p>JythonShellServer works, but I only just wrote it this morning, so consider it alpha quality at the moment. Check out the <a href="http://github.com/EnigmaCurry/jython-shell-server/tree">project page on github.</a></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="highlight"><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="highlight"><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="highlight"><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="highlight"><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="highlight"><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="highlight"><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="highlight"><pre>sudo apt-get install ncurses-term
</pre></div>


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

<div class="highlight"><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="highlight"><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="highlight"><pre><span class="p">(</span><span class="nb">defun</span> <span class="nv">epg-disable-agent</span> <span class="p">()</span>
  <span class="s">&quot;Make EasyPG bypass any gpg-agent&quot;</span>
  <span class="p">(</span><span class="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">ad-enable-advice</span> <span class="ss">&#39;epg--start</span> <span class="ss">&#39;around</span> <span class="ss">&#39;advice-epg-disable-agent</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">ad-activate</span> <span class="ss">&#39;epg--start</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">message</span> <span class="s">&quot;EasyPG gpg-agent bypassed&quot;</span><span class="p">))</span>

<span class="p">(</span><span class="nb">defun</span> <span class="nv">epg-enable-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="nv">interactive</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">ad-disable-advice</span> <span class="ss">&#39;epg--start</span> <span class="ss">&#39;around</span> <span class="ss">&#39;advice-epg-disable-agent</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">ad-activate</span> <span class="ss">&#39;epg--start</span><span class="p">)</span>
  <span class="p">(</span><span class="nv">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>
  </channel>
</rss>
