<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>sixohthree.com</title>
	<atom:link href="http://sixohthree.com/feed" rel="self" type="application/rss+xml" />
	<link>http://sixohthree.com</link>
	<description>The Weblog of Adam Backstrom</description>
	<lastBuildDate>Mon, 25 Jan 2010 18:28:01 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Subversion: Missing Features</title>
		<link>http://sixohthree.com/972/subversion-missing-features</link>
		<comments>http://sixohthree.com/972/subversion-missing-features#comments</comments>
		<pubDate>Mon, 25 Jan 2010 17:31:59 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Personal]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>

		<guid isPermaLink="false">http://sixohthree.com/?p=972</guid>
		<description><![CDATA[I love many things about git, but I use Subversion at my day job. Two git features please me enough that I took the time to build them into my svn workflow: paged diffs and &#8220;commit -v.&#8221;
Paged Diffing
Many times I require my svn diff output to be paged through less. Rather than append &#124; less [...]]]></description>
			<content:encoded><![CDATA[<p>I love many things about <a href="http://git-scm.com/">git</a>, but I use <a href="http://subversion.tigris.org/">Subversion</a> at my day job. Two git features please me enough that I took the time to build them into my svn workflow: paged diffs and &#8220;commit -v.&#8221;</p>
<h3>Paged Diffing</h3>
<p>Many times I require my <code>svn diff</code> output to be paged through <code>less</code>. Rather than append <code>| less</code> continually, I created the following wrapper script as <code>~/bin/svn</code>:</p>
<pre><code>#!/bin/bash
[ "$1" = "less" ] &amp;&amp; shift &amp;&amp; exec /usr/bin/svn diff "$@" | less
exec /usr/bin/svn "$@"</code></pre>
<p>With this script, I have a new <code>svn less</code> operation that pages diff output.</p>
<p>Note that <code>~/bin/svn</code> must be before <code>/usr/bin</code> in your <code>$PATH</code>, or the real <code>svn</code> binary will take precedence over the wrapper.</p>
<h3>Verbose Commits</h3>
<p>I would wager that many <code>git</code> users type <code>git commit -av</code> more than once a day to commit all changed files and display the current diff in their editor. Very handy if you need a reference when creating your commit log message. Subversion will tell you what files have changed, but does not display the diff. I use the following <code>vim</code> mapping, adapted from the <a href="http://vim.wikia.com/wiki/Open_SVN_diff_window">Vim wiki</a>:</p>
<pre><code>map &lt;leader&gt;d :vnew&lt;CR&gt;:read !svn diff&lt;CR&gt;:set syntax=diff buftype=nofile&lt;CR&gt;ggdd</code></pre>
<p>This command opens a new window vertically, then fills that window with the diff of the current directory. Unfortunately this is of only limited usefulness: since <code>vim</code> does not know what files you are committing, it displays a diff of all changes in the current directory. Also, <code>svn commit</code> with no arguments seems to move the current directory up one level, which can give an inaccurate diff. I use <code>svn commit *</code> when I need to work around this feature. The <a href="http://vim.wikia.com/wiki/Open_SVN_diff_window">wiki page</a> has some variations that appear to work around these problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://sixohthree.com/972/subversion-missing-features/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>My Browser is Sentient</title>
		<link>http://sixohthree.com/962/my-browser-is-sentient</link>
		<comments>http://sixohthree.com/962/my-browser-is-sentient#comments</comments>
		<pubDate>Tue, 05 Jan 2010 21:01:44 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sixohthree.com/?p=962</guid>
		<description><![CDATA[Noticed some weird traffic coming into my router this morning.]]></description>
			<content:encoded><![CDATA[<p>Noticed some weird traffic coming into my router this morning:</p>
<p><a href="http://sixohthree.com/files/2010/01/traffic.png"><img class="alignnone size-full wp-image-961" title="traffic" src="http://sixohthree.com/files/2010/01/traffic.png" alt="traffic" width="486" height="211" /></a></p>
<p>The incoming traffic (blue line) was maxed out at my bandwidth cap, even though I wasn&#8217;t downloading anything. After a few failed attempts at figuring out what was going on, I started closing browser tabs, resulting in the sustained dropoff near the end of the graph. I reopened the tabs (small bump closer to the end) but the incoming traffic did not spike.</p>
<p>Gmail and a few other pages were open, but nothing that would explain the traffic spike I saw. Maybe the ghost in the machine was watching Hulu.</p>
]]></content:encoded>
			<wfw:commentRss>http://sixohthree.com/962/my-browser-is-sentient/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ding III</title>
		<link>http://sixohthree.com/950/ding-iii</link>
		<comments>http://sixohthree.com/950/ding-iii#comments</comments>
		<pubDate>Mon, 05 Oct 2009 17:07:36 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Games]]></category>
		<category><![CDATA[wow]]></category>

		<guid isPermaLink="false">http://sixohthree.com/?p=950</guid>
		<description><![CDATA[Third time's a charm.]]></description>
			<content:encoded><![CDATA[<p><a href="http://sixohthree.com/files/2009/10/ScreenShot_100509_121827.jpeg"><img class="size-medium wp-image-953 alignright" src="http://sixohthree.com/files/2009/10/ScreenShot_100509_121827-300x187.jpg" alt="ScreenShot_100509_121827" width="300" height="187" /></a>Continuing <a href="http://sixohthree.com/355/ding">the</a> <a href="http://sixohthree.com/382/ding-2">tradition</a>: ding.</p>
<p>Looking through the archives, it seems I never documented the level 70 ding for Cetoh. The screenshot has been lost, probably to a dead hard drive, so the exact date escapes me. But, the rogue was first to 60, the priest was first to 70, and the death knight was first to 80. Old characters lag behind: the rogue sits at 68, and the priest hasn&#8217;t moved past 70. Gotta wonder what I&#8217;ll be playing at level 85.</p>
<p>The world looks a bit different since I last hit the cap. Cataclysm has been announced, and promises to reshape Azeroth. The achievements system has been brought online. Mounts are available at level 20. People have started getting their <a href="http://www.wowhead.com/?item=44177">Reins of the Violet Proto-Drake</a>.</p>
<p>My death knight is Exalted with two factions (my first two on any character). 1,008 quests brought her from level 55 to level 80, over the course of nearly 11 months. (Winning a duel is a requirement of the death knight starter quest line, and my character became <a href="http://www.wowhead.com/?achievement=1157">Duel-icious</a> on 2008-11-13.) She <a href="http://www.wowhead.com/?achievement=34">Toured the Fjord</a>, got <a href="http://www.wowhead.com/?achievement=33">Bored in Borean</a>, saw the <a href="http://www.wowhead.com/?achievement=35">Might of Dragonblight</a>, and was just two quests shy of that <a href="http://www.wowhead.com/?achievement=37">Grizzly Shizzle</a> at ding. She has caught 1,405 fish and &#8220;other things&#8221;; overall her skills languish at Cooking 206, Fishing 340, Herbalism 158, and Mining 169. She is still waiting for Artisan flying.</p>
]]></content:encoded>
			<wfw:commentRss>http://sixohthree.com/950/ding-iii/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tunneling Everything through SOCKS5</title>
		<link>http://sixohthree.com/942/tunneling-everything-through-socks5</link>
		<comments>http://sixohthree.com/942/tunneling-everything-through-socks5#comments</comments>
		<pubDate>Sun, 13 Sep 2009 03:14:24 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[web]]></category>

		<guid isPermaLink="false">http://sixohthree.com/?p=942</guid>
		<description><![CDATA[Kicking that VPN habit.]]></description>
			<content:encoded><![CDATA[<p>At my current employer, many administrator-level services (SSH, SQL, development servers) must be accessed over a VPN. Generally speaking, this is a Good Thing. However, it can be inconvenient: only one VPN connection is allowed per user, and all traffic is sent over the VPN regardless of its final destination.</p>
<p>The ssh client included in OpenSSH includes a very easy to use SOCKS5 proxy server: ssh -D 9999 server.example.com opens a normal connection to server.example.com, but also creates a SOCKS5 server at localhost:9999 that routes traffic from supported applications through the remote server. Firefox includes support for SOCKS5, and add-ons like the <a href="https://addons.mozilla.org/en-US/firefox/addon/60">Web Developer</a> toolbar and <a href="https://addons.mozilla.org/en-US/firefox/addon/2464">FoxyProxy</a> can quickly enable or disable the proxy settings. I&#8217;ve used this to great success in the past, but, as with most things, there is room for improvement.</p>
<p><strong>Server names and IPs have been modified from their original values.</strong></p>
<h3>Fine-tuning Firefox</h3>
<p>While you can provide Firefox with a simple SOCKS5 host and port, the software also supports <a href="http://en.wikipedia.org/wiki/Proxy_auto-config">proxy auto-config</a> (PAC) files. Both Firefox (natively) and Safari (via Network preferences) support PAC. The following PAC file tells the application to route traffic for anything at example.com through the proxy server, and directly connect to everything else. This keeps your non-business traffic from routing through business servers, so you can stream Netflix and still access those servers behind the firewall.</p>
<pre><code>function FindProxyForURL(url, host)
{
	if(shExpMatch(url, '*.example.com/*')) return "SOCKS localhost:9999";
	return "DIRECT";
}</code></pre>
<h3>Proxy Everything</h3>
<p>While ssh can create a proxy server, there is no built-in support for connecting to a host through a proxy. The same is true for many other applications, particularly console apps. Enter <a href="http://tsocks.sourceforge.net/">tsocks</a>, a wrapper library that intercepts TCP calls and routes them through a SOCKS proxy. tsocks exploits something call preloaded libraries: when ssh is launched, special flags in the shell force a load of the tsocks library. My preferred way of running tsocks is to run it with no arguments, which sets up the preloading for any program run in the shell from that point forward.</p>
<p><a href="http://marc-abramowitz.com/">Marc Abramowitz</a> did some great work <a href="http://marc-abramowitz.com/archives/2006/01/29/building-tsocks-on-mac-os-x/">getting tsocks to compile under Mac OS X.</a> I made a few tweaks to his patch, and <a href="http://sixohthree.com/files/2009/09/tsocks-1.8-macosx-sixohthree.com.patch">release it here</a>. To apply the patch, take the same steps that Marc mentions on his site, but use my patch instead.</p>
<p>After tsocks is installed, running something through your proxy is easy.</p>
<pre><code>$ ssh -f -N -D 9999 host.example.com
$ tsocks
$ ssh firewalled.example.com</code></pre>
<p>The first line creates a proxy server, the second prepares tsocks, and the third opens an SSH connection using the proxy defined in /etc/tsocks.conf. For completeness, here is my tsocks.conf:</p>
<pre><code>local = 10.0.0.0/255.0.0.0

path {
	reaches = 129.21.0.0/255.255.0.0

	server = 127.0.0.1
	server_port = 9999

	server_type = 5
}</code></pre>
<p>That&#8217;s all. Secure access to firewalled servers through HTTP and SSH. Works great, as long as you have one server that can be used as a gateway (available for SSH from outside the network, but able to access things inside).</p>
]]></content:encoded>
			<wfw:commentRss>http://sixohthree.com/942/tunneling-everything-through-socks5/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Removing All Partitions in Mac OS X</title>
		<link>http://sixohthree.com/934/removing-all-partitions-in-mac-os-x</link>
		<comments>http://sixohthree.com/934/removing-all-partitions-in-mac-os-x#comments</comments>
		<pubDate>Tue, 08 Sep 2009 17:41:05 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Computers]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[security]]></category>
		<category><![CDATA[terminal]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://sixohthree.com/?p=934</guid>
		<description><![CDATA[Here's now to "remove" all partitions on a disk under Mac OS X by clobbering the partition map.]]></description>
			<content:encoded><![CDATA[<p>When setting up a new <a href="http://www.truecrypt.org/">TrueCrypt</a> device under Mac OS X, you may receive this message if you try to encrypt a whole disk rather than a partition:</p>
<p><a href="http://sixohthree.com/files/2009/09/device-contains-partitions.png"><img class="alignnone size-full wp-image-931" src="http://sixohthree.com/files/2009/09/device-contains-partitions.png" alt="device-contains-partitions" width="394" height="183" /></a></p>
<p>I could not find a way to remove the partition via the Mac OS X Disk Utility, so I resorted to some terminal work. By clobbering the first few bytes of the disk&#8217;s partition map, I essentially made the whole disk look like random garbage, and TrueCrypt no longer presented a warning. <span style="color: #ff0000">This will cause data loss, so be careful.</span></p>
<p>First, find the drive&#8217;s device number using Disk Utility. Right click on the drive (not one of the partitions) and select &#8220;Information.&#8221;</p>
<p><a href="http://sixohthree.com/files/2009/09/right-click-info.jpg"><img class="alignnone size-full wp-image-933" src="http://sixohthree.com/files/2009/09/right-click-info.jpg" alt="right-click-info" width="274" height="172" /></a></p>
<p>Look for &#8220;Disk Identifier&#8221; in the property list. In this case, my drive is called disk3, which corresponds to /dev/disk3 on the filesystem. Tomorrow it might be disk4 or disk6, so don&#8217;t make any assumptions here. Failure to find the correct drive number in this step will cause you to erase the wrong drive in a future step.</p>
<p><a href="http://sixohthree.com/files/2009/09/device-information.png"><img class="alignnone size-full wp-image-932" src="http://sixohthree.com/files/2009/09/device-information.png" alt="device-information" width="317" height="219" /></a></p>
<p>Open up your terminal and umount this disk&#8217;s volumes:</p>
<ul>
<li>sudo umount -f /dev/<em>&lt;identifier&gt;</em>*</li>
</ul>
<p>Unmounting drives in the Finder will make the disk unavailable in /dev, and we need this block device if we&#8217;re going to clobber the filesystem.</p>
<p>Once the partitions are unmounted, we can write junk to the partition table and essentially unformat the drive. <span style="color: #ff0000">This is the dangerous part, so don&#8217;t screw it up or you will destroy the wrong drive, lose all your data, and seriously hate life.<br />
</span></p>
<ul>
<li>sudo dd if=/dev/zero of=/dev/<em>&lt;identifier&gt;</em> bs=1 count=1024</li>
</ul>
<p>After writing zeroes to the front of the drive, TrueCrypt happily made an encrypted volume on the disk.</p>
]]></content:encoded>
			<wfw:commentRss>http://sixohthree.com/934/removing-all-partitions-in-mac-os-x/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Information Gathering</title>
		<link>http://sixohthree.com/914/information-gathering</link>
		<comments>http://sixohthree.com/914/information-gathering#comments</comments>
		<pubDate>Wed, 26 Aug 2009 12:07:04 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://sixohthree.com/?p=914</guid>
		<description><![CDATA[The lure of data is still strong, but how do you organize it all?]]></description>
			<content:encoded><![CDATA[<p><a href="/~adam/wp-uploads/2009/08/devonthink.png"><img class="alignright size-medium wp-image-913" src="/~adam/wp-uploads/2009/08/devonthink-300x199.png" alt="devonthink" width="300" height="199" /></a>I&#8217;ve written before about the <a href="/167/the-lure-of-data">lure of data</a>. In a similar vein, it&#8217;s been  suggested that information <a href="http://scienceblogs.com/notrocketscience/2009/07/why_information_is_its_own_reward_-_same_neurons_signal_thir.php">triggers the reward response</a> in our brains. Whatever the chemical reasons behind it all, I am a data packrat.</p>
<p>My biggest problem with being a data packrat is organization. It took me countless searches to find the above article at scienceblogs.com, in part because I first combed through a number of my own repositories before falling back on Google searches. Did I put that in <a href="http://delicious.com/">Delicious</a>? Is it in my <a href="http://www.google.com/reader/">feed reader</a>&#8217;s history? Repeat that for 20 minutes.</p>
<p>It&#8217;s revealing to enumerate all the places I might put a piece of data:</p>
<ol>
<li>Twitter</li>
<li>P2 blog</li>
<li>Delicious</li>
<li>Google Reader (which offers &#8220;share,&#8221; &#8220;like&#8221; and &#8220;star,&#8221; as well as custom tags)</li>
<li>MediaWiki (public)</li>
<li>MediaWiki (private, mostly a relic from before Google Docs)</li>
<li>This blog</li>
<li><a href="http://www.devon-technologies.com/products/devonthink/">DEVONthink</a></li>
<li>Firefox bookmarks (I generally avoid these)</li>
</ol>
<p>That doesn&#8217;t even hit possible storage locations for images. I can tick off five of those without any effort. Most of these repositories will become obsolete over time, having fallen out of fashion or been replaced by something bigger and better. Some data moves forward into the new tool, some stagnates out of sight.</p>
<p>I have no answers, here.</p>
]]></content:encoded>
			<wfw:commentRss>http://sixohthree.com/914/information-gathering/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Video in the Browser</title>
		<link>http://sixohthree.com/884/video-in-the-browser</link>
		<comments>http://sixohthree.com/884/video-in-the-browser#comments</comments>
		<pubDate>Mon, 15 Jun 2009 23:25:08 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[ogg]]></category>
		<category><![CDATA[oggtheora]]></category>
		<category><![CDATA[Video]]></category>
		<category><![CDATA[vorbis]]></category>

		<guid isPermaLink="false">http://sixohthree.com/?p=884</guid>
		<description><![CDATA[Ogg Vorbis video, in the browser, no plugins required.]]></description>
			<content:encoded><![CDATA[<p>Ogg Theora video, in the browser, no plugins required.</p>
<p><a href="/~adam/wp-uploads/2009/06/ogg-vorbis-browser1.png"><img class="alignnone size-full wp-image-889" src="/~adam/wp-uploads/2009/06/ogg-vorbis-browser1.png" alt="ogg-vorbis-browser" width="590" height="539" /></a></p>
<p>I will begin taking this for granted immediately. Thanks, <a href="http://www.mozilla.com/en-US/firefox/3.5b4/releasenotes/">Firefox 3.5b4</a>.</p>
<p>Update: Ogg Theora has been <a href="http://arstechnica.com/open-source/news/2009/07/decoding-the-html-5-video-codec-debate.ars">backed out</a> of the HTML5 draft spec due to lack of consensus from the big browser makers. Like the &lt;img&gt; tag, support for formats will be left in the hands of developers. A bit sad, really.</p>
]]></content:encoded>
			<wfw:commentRss>http://sixohthree.com/884/video-in-the-browser/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bash Completion</title>
		<link>http://sixohthree.com/867/bash-completion</link>
		<comments>http://sixohthree.com/867/bash-completion#comments</comments>
		<pubDate>Fri, 05 Jun 2009 00:54:42 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Scripting]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[compgen]]></category>
		<category><![CDATA[complete]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://sixohthree.com/?p=867</guid>
		<description><![CDATA[It would be difficult to <em>not</em> like bash's programmable completion. It's too bad I've had such a hard time wrapping my head around the programmable completion toolkit.]]></description>
			<content:encoded><![CDATA[<p>It would be difficult to <em>not</em> like bash&#8217;s <a href="http://www.gnu.org/software/bash/manual/bashref.html#Programmable-Completion">programmable completion</a>. Tab completion is addictive, and expanding it past files and folders into usernames, hostnames, and, well, anything you can dream up and put in a function, has incredible potential.</p>
<p>It&#8217;s too bad I&#8217;ve had such a hard time wrapping my head around the programmable completion toolkit, <code>complete</code> and <code>compgen</code>.</p>
<h3 id="867_getting-there_1">Getting There</h3>
<p>I have a function that works like <code>cd</code>, but prepends a specific directory. Our web files are stored in <code>/some/dir/webapp</code>, and I want that directory at my fingertips at all times. Here&#8217;s the function:</p>
<pre><code>wa() { cd /web/pscpages/webapp/$1 ; }</code></pre>
<p>With this function, <code>wa</code> brings me to <code>webapp</code>; <code>wa project1</code> brings me to <code>webapp/project1</code>; and so on. I just provide the full sub-path from <code>webapp</code>. Ideally, I would be able to tab-complete directories in <code>webapp</code>.</p>
<p><code>complete</code> can pull a list of possible completions from a number of sources: &#8220;actions&#8221; (like files, directories, commands, shell keywords), command output, a wordlist separated by some whitespace, or the output of a bash function, to name a few. What you&#8217;ve typed so far (the &#8220;current word&#8221;) will be used to filter all the possible completions returned by that source. Say you&#8217;ve typed &#8220;pro&#8221; and then hit tab to autocomplete. The returned completions need to match &#8220;pro&#8221; at the start of the string, meaning you can&#8217;t match against absolute paths like <code>/some/dir/webapp/project1</code>.</p>
<p><code>compgen</code> can be used to generate a list of possible completions. Matches will be output one per line, and can be piped around for transformations just like any other shell command.</p>
<p>Between these two tools, we have everything we need to autocomplete paths starting in a certain directory. Here&#8217;s a <code>compgen</code> that gives us directories matching a specified string:</p>
<pre><code>compgen -d /some/dir/webapp/</code></pre>
<p>Sample output:</p>
<pre><code>/some/dir/webapp/.svn
/some/dir/webapp/project1
/some/dir/webapp/templates
/some/dir/webapp/images</code></pre>
<p>We need to trim leading directories so &#8220;pro&#8221; matches &#8220;project1.&#8221; We should also append <code>/</code> to the pathnames, since we&#8217;re always matching directories:</p>
<pre><code>compgen -S/ -d /some/dir/webapp/ | cut -b 18-</code></pre>
<p>Playing around with <code>compgen</code>&#8217;s arguments, we can further filter the completion list by appending to our string, sort of an implied glob. Use <code>/some/dir/webapp/p</code>, and subdirectories starting with &#8220;p&#8221; will be returned. This is exactly what we want: <code>compgen</code> takes care of all the filtering for us. We have access to a couple special variables to examine the word the user is expanding. For now, it&#8217;s enough just to grab <var>${COMP_WORDS[COMP_CWORD]}</var> and append it to our path.</p>
<p>When completions are generated by a function, they&#8217;re passed back to <code>complete</code> by the <var>$COMPREPLY</var> environment variable. Pulling this all together, we can now create our completion function:</p>
<pre><code>_webapp() {
    local cur
    cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $( compgen -S/ -d /some/dir/webapp/$cur | cut -b 18- ) )
}</code></pre>
<p>All that&#8217;s left is to tell bash to use this function to complete our argument to <code>wa</code>.</p>
<pre><code>complete -o nospace -F _webapp wa</code></pre>
<h3 id="867_the-fruits_1">The Fruits</h3>
<p>So, that does it. Our original wrapper to <code>cd</code>, combined with our autocomplete functionality, looks like this:</p>
<pre><code>wa() { cd /some/dir/webapp/$1 ; }
_webapp() {
    local cur
    cur=${COMP_WORDS[COMP_CWORD]}
    COMPREPLY=( $( compgen -S/ -d /some/dir/webapp/$cur | cut -b 18- ) )
}
complete -o nospace -F _webapp wa</code></pre>
<p>Voila. Tab completion in a directory that&#8217;s not <var>$PWD</var>, and it even works with subdirectories. I hope this makes autocompletion a little clearer for others.</p>
]]></content:encoded>
			<wfw:commentRss>http://sixohthree.com/867/bash-completion/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Firefox Personas</title>
		<link>http://sixohthree.com/860/firefox-personas</link>
		<comments>http://sixohthree.com/860/firefox-personas#comments</comments>
		<pubDate>Fri, 29 May 2009 12:39:17 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[web]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[personalization]]></category>
		<category><![CDATA[skinning]]></category>
		<category><![CDATA[themes]]></category>

		<guid isPermaLink="false">http://blogs.bwerp.net/?p=860</guid>
		<description><![CDATA[Easy theming for Mozilla Firefox.]]></description>
			<content:encoded><![CDATA[<p>A <a href="http://www.wowhead.com/?blog=98108">post over at Wowhead</a> brought <a href="http://personas.services.mozilla.com/">Firefox Personas</a> to my attention. Once you have the Personas addon installed, new themes are super easy to use: the Personas menu gives you a bunch of starter personas, including &#8220;new,&#8221; &#8220;popular&#8221; and by category (with a randomizer). All the personas are previewed live as you scroll through the menus, which is the real killer feature here. Even the mouseovers on the Personas site skin your browser in real time.</p>
<p>Here&#8217;s a small sample of personas. I usually hide some toolbars for Firefox screenshots, but personas tend to look better with a larger canvas.</p>

<a href='http://sixohthree.com/860/firefox-personas/abstract-black' title='abstract-black'><img width="150" height="150" src="http://sixohthree.com/files/2009/05/abstract-black-150x150.png" class="attachment-thumbnail" alt="Abstract Black" title="abstract-black" /></a>
<a href='http://sixohthree.com/860/firefox-personas/groovy-blue' title='groovy-blue'><img width="150" height="150" src="http://sixohthree.com/files/2009/05/groovy-blue-150x150.png" class="attachment-thumbnail" alt="Groovy Blue" title="groovy-blue" /></a>
<a href='http://sixohthree.com/860/firefox-personas/mozilla-firefox' title='mozilla-firefox'><img width="150" height="150" src="http://sixohthree.com/files/2009/05/mozilla-firefox-150x150.png" class="attachment-thumbnail" alt="Mozilla Firefox" title="mozilla-firefox" /></a>
<a href='http://sixohthree.com/860/firefox-personas/viva' title='viva'><img width="150" height="150" src="http://sixohthree.com/files/2009/05/viva-150x150.png" class="attachment-thumbnail" alt="Viva" title="viva" /></a>

]]></content:encoded>
			<wfw:commentRss>http://sixohthree.com/860/firefox-personas/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>On Entropy</title>
		<link>http://sixohthree.com/858/on-entropy</link>
		<comments>http://sixohthree.com/858/on-entropy#comments</comments>
		<pubDate>Thu, 28 May 2009 19:40:25 +0000</pubDate>
		<dc:creator>Adam</dc:creator>
				<category><![CDATA[Video]]></category>
		<category><![CDATA[hulu]]></category>
		<category><![CDATA[tv]]></category>

		<guid isPermaLink="false">http://blogs.bwerp.net/?p=858</guid>
		<description><![CDATA[Hulu's desktop application has been released.]]></description>
			<content:encoded><![CDATA[<p><a href="/~adam/wp-uploads/2009/05/hulu-loading-random-video.png"><img class="alignnone size-full wp-image-857" src="/~adam/wp-uploads/2009/05/hulu-loading-random-video.png" alt="hulu-loading-random-video" width="555" height="288" /></a></p>
<p><a href="http://www.hulu.com/labs/hulu-desktop">Hulu&#8217;s desktop application</a> has been released.</p>
]]></content:encoded>
			<wfw:commentRss>http://sixohthree.com/858/on-entropy/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>