cf38a58b1927

Add the rest of the blog entries.
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Wed, 23 Dec 2009 20:24:31 -0500
parents d3778a652c44
children 4ac1bf2cbaa2
branches/tags (none)
files content/blog/2009/01/deploying-site-fabric-and-mercurial.html content/blog/2009/01/going-open-source.html content/blog/2009/01/site-redesign.html content/blog/2009/02/how-and-why-i-dj.html content/blog/2009/02/how-i-shoot-dances.html content/blog/2009/03/candy-colored-terminal.html content/blog/2009/03/mercurial-bash-prompts.html content/blog/2009/04/why-people-dont-like-metal.html content/blog/2009/05/what-i-hate-about-mercurial.html content/blog/2009/06/how-to-contribute-to-mercurial.html content/blog/2009/08/a-guide-to-branching-in-mercurial.html content/blog/2009/11/my-sitesprint-project-lindyhub.html layout/_post.html layout/skeleton/_base.html layout/skeleton/_innerlisting.html media/css/base.css

Changes

--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/01/deploying-site-fabric-and-mercurial.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,216 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Deploying with Fabric &amp; Mercurial"
+    snip: "Trimming typing."
+    created: 2009-01-15 20:51:09
+%}
+
+{% block article %}
+
+Earlier tonight I added support for the [Mint][] [Bird Feeder][] plugin to my
+site's [RSS feeds][]. Bird Feeder isn't designed to work with [Django][] so I
+had to change a few things to get it up and running. I mostly followed the
+[instructions on
+Hicks-Wright.net](http://hicks-wright.net/blog/minty-django-feeds/) with a few
+tweaks.
+
+While I was trying to get things running smoothly I had to redeploy the site a
+bunch of times so I could test the changes I made. If I were simply FTP'ing
+the files over each time I wanted to redeploy it would have been a huge pain.
+Fortunately, I have another way to do it that cuts down on my typing.
+
+[Mint]: http://haveamint.com
+[Bird Feeder]: http://haveamint.com/peppermill/pepper/11/bird_feeder/
+[RSS feeds]: /rss/
+[Django]: http://djangoproject.com/
+
+[TOC]
+
+My Basic Deployment Steps
+-------------------------
+
+The code for my site is stored in a Mercurial repository. There are actually
+three copies of the repository that I use:
+
+* One is on my local machine, which I commit to as I make changes.
+* One is on [BitBucket][], which I use to share the code with the public.
+* One is on my host's webserver, and is what actually gets served as the website.
+
+When I'm ready to deploy a new version of the site, I push the changes I've
+made on my local repository to the one on BitBucket, then pull the changes
+from BitBucket down to the server. Using push/pull means I don't have to worry
+about transferring the files myself. Using BitBucket in the middle (instead of
+going right from my local machine to the server) means I don't have to worry
+about serving either repository myself and dealing with port forwarding or
+security issues.
+
+[BitBucket]: http://bitbucket.org
+
+Putting BitBucket in the Middle
+-------------------------------
+
+Using BitBucket as an intermediate repository is actually fairly simple. Here
+are the basic steps I use to get a project up and running like this.
+
+First, create a new repository on BitBucket. Make sure the name is what you
+want. Feel free to make it private if you just want it for this, or public if
+you want to [go open source][].
+
+[go open source]: /blog/entry/2009/1/13/going-open-source/
+
+### Set Up Your Local Machine
+
+Clone this new, empty repository to your local machine. If you already have
+code written you'll need to copy it into this folder after cloning. I don't
+know if there's a way to push a brand-new repository to BitBucket; if you know
+how please tell me.
+
+On your local machine, edit the `.hg/hgrc` file in the repository and change
+the default path to:
+
+	default = ssh://hg@bitbucket.org/username/repositoryname/
+
+That will let you push/pull to and from BitBucket over SSH. Doing it that way
+means you can use public/private key authentication and avoid typing your
+password every single time. A fairly comprehensive guide to that can be found
+[here](http://www.securityfocus.com/infocus/1810). You can ignore the
+server-side configuration; you just need to add your public key on BitBucket's
+account settings page and you should be set.
+
+**UPDATE:**  I didn't realize it before, but BitBucket has a [guide to using SSH with BitBucket](http://bitbucket.org/help/using-ssh/).  It's definitely worth looking at.
+
+Now you should be able to use `hg push` and `hg pull` on your local machine to
+push and pull changes to and from the BitBucket repository. The next step is
+getting it set up on the server side.
+
+### Set Up Your Server
+
+On your server, use `hg clone` to clone the BitBucket repository to wherever
+you want to serve it from. Edit the `.hg/hgrc` file in that one and change the
+default path to the same value as before:
+
+	default = ssh://hg@bitbucket.org/username/repositoryname/
+
+Once again, set up public/private key authentication; this time between the
+server and BitBucket. You can either copy your public and private keys from
+your local machine to the server (if you trust/own it) or you can create a new
+pair and add its public key to your BitBucket account as well.
+
+While you're at it, set up public/private key authentication to go from your
+local machine to your server too. It'll pay off in the long run.
+
+Now that you've got both sides working, you can develop and deploy like so:
+
+* Make changes on your local machine, committing as you go.
+* Push the changes to BitBucket.
+* SSH into your server and pull the changes down.
+* Restart the web server process if necessary.
+
+Not too bad! Instead of manually managing file transfers you can let Mercurial
+do it for you. It'll only pull down the files that have changed, and will
+always put them in exactly the right spot. That's pretty convenient, but we
+can do better.
+
+Weaving it All Together with Fabric
+-----------------------------------
+
+Being able to push and pull is all well and good, but that's still a lot of
+typing. You need to enter a command to push your changes, a command to SSH to
+the server, a command to change to the deploy directory, a command to pull the
+changes, and a command to restart the server process. That's five commands,
+which is four commands too many for me.
+
+To automate the process, I use the wonderful [Fabric][] tool. If you haven't
+seen it before you should take a look. To follow along with the rest of the
+section you should read the examples on the site and install Fabric on your
+local machine.
+
+### My Current Setup
+
+Here's the fabfile I use for deploying my site to my host ([WebFaction][]).
+It's pretty specific to my needs but I'm sure it will give you an idea of
+where to start.
+
+[Fabric]: http://www.nongnu.org/fab/
+[WebFaction]: http://www.webfaction.com?affiliate=sjl
+
+	#!python
+	def prod():
+	    """Set the target to production."""
+	    set(fab_hosts=['sjl.webfactional.com'])
+	    set(fab_key_filename='/Users/sjl/.ssh/stevelosh')
+	    set(remote_app_dir='~/webapps/stevelosh/stevelosh')
+	    set(remote_apache_dir='~/webapps/stevelosh/apache2')
+
+	def deploy():
+	    """Deploy the site."""
+	    require('fab_hosts', provided_by = [prod,])
+	    local("hg push")
+	    run("cd $(remote_app_dir); hg pull; hg update")
+	    run("cd $(remote_app_dir); python2.5 manage.py syncdb")
+	    run("$(remote_apache_dir)/bin/stop; sleep 1; $(remote_apache_dir)/bin/start")
+
+	def debugon():
+	    """Turn debug mode on for the production server."""
+	    require('fab_hosts', provided_by = [prod,])
+	    run("cd $(remote_app_dir); sed -i -e 's/DEBUG = .*/DEBUG = True/' deploy.py")
+	    run("$(remote_apache_dir)/bin/stop; sleep 1; $(remote_apache_dir)/bin/start")
+
+	def debugoff():
+	    """Turn debug mode off for the production server."""
+	    require('fab_hosts', provided_by = [prod,])
+	    run("cd $(remote_app_dir); sed -i -e 's/DEBUG = .*/DEBUG = False/' deploy.py")
+	    run("$(remote_apache_dir)/bin/stop; sleep 1; $(remote_apache_dir)/bin/start")
+
+When I'm finished committing to my local repository and I want to deploy the
+site, I just use the command `fab prod deploy` on my local machine. Fabric
+pushes my local repository to BitBucket, logs into the server (with my public
+key&mdash;no typing in passwords), pulls down the new changes from BitBucket
+and restarts the server process.
+
+I also set up a couple of debug commands so I can type `fab prod debugon` and
+`fab prod debugoff` to change the `settings.DEBUG` option of my Django app.
+Sometimes it's useful to turn on debug to find out exactly why a page is
+breaking on the server.
+
+### Extending It
+
+The reason I split off the `prod` command is so I can set up a separate test
+app (on the server) in the future and reuse the `deploy` and `debug` commands.
+All I'd need to do is add a `test` command, which might look something like
+this:
+
+	#!python
+	def test():
+	    """Set the target to test."""
+	    set(fab_hosts=['sjl.webfactional.com'])
+	    set(fab_key_filename='/Users/sjl/.ssh/stevelosh')
+	    set(remote_app_dir = '~/webapps/stevelosh-test/stevelosh')
+	    set(remote_apache_dir = '~/webapps/stevelosh-test/apache2')
+
+Deploying the test site would then be a simple `fab test deploy` command.
+
+Why Should You Try This?
+------------------------
+
+After you've gotten all of this set up the first time it will start saving you
+time every time you deploy. It also prevents stupid mistakes like FTP'ing your
+files to the wrong directory on the server. It frees you from those headaches
+and lets you concentrate on the real work to be done instead of the busywork.
+Plus setting it up again for a second project is a breeze after you've done it
+once.
+
+Obviously the exact details of this won't be a perfect fit for everyone. Maybe
+you prefer using git and [GitHub][] for version control. I'm sure there's a
+similar way to automate the process on that side of the fence. If you decide
+to write something about the details of that please let me know and I'll link
+it here.
+
+My hope is that this will at least give you some ideas about saving yourself
+some time. If that helps you create better websites, I'll be happy. Please
+feel free to comment with any questions or thoughts you have!
+
+[GitHub]: http://github.com/
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/01/going-open-source.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,139 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Going Open Source"
+    snip: "Why I’m making the code to this website public."
+    created: 2009-01-13 20:08:56
+%}
+
+{% block article %}
+
+Well, I've finally taken the plunge and made this site open source. It's held
+in a [Mercurial][] repository, but you can view or download the source code
+from <http://bitbucket.org/sjl/stevelosh/> without any special tools.
+
+The site was built with the [Django][] framework. If you want to know more
+check out the [project page][]. This post isn't going to duplicate what's
+there; instead I want to write about why I made the site open source at all.
+There are a couple of main reasons, and not *all* of them are selfish!
+
+[Mercurial]: http://www.selenic.com/mercurial/wiki/
+[Django]: http://djangoproject.com/
+[project page]: /projects/stevelosh-com
+
+I Get More Traffic
+------------------
+
+The first reason to make a site open source is to try to get more hits. You
+certainly don't *lose* any hits from doing it, and when developers find your
+link on places like [DjangoSites][] they might be more inclined to visit if
+they knew they could look at the source code later.
+
+You also have the chance to post on [Twitter][], [Tumblr][], or other places
+about the source code of the site. Each of those posts can expose more people
+to the website. It's easy to overdo this though. I heartily agree with the
+sentiments of
+[howtousetwitterformarketingandpr.com](http://howtousetwitterformarketingandpr.com)
+on that issue.
+
+Don't worry, I won't be obnoxious about it.
+
+[DjangoSites]: http://djangosites.org/
+[Twitter]: http://twitter.com/
+[Tumblr]: http://tumblr.com/
+
+I Can Give Back to the (Programming) Community
+----------------------------------------------
+
+Yeah, I know.  It sounds cliched, but it's true.  
+
+The open source community has produced a *ridiculous* amount of software, some
+of which we use every day. Software like [Apache][], [Django][], and countless
+others simply wouldn't exist in anything remotely close to their current
+forms.
+
+Being able to look at the source code for a particular project can be
+extremely helpful to someone trying to learn how to do something similar.
+Instead of firing up an email client and sending a message to the creator they
+can simply look at how it works themselves. They can download it, tweak it,
+break it, and figure out what makes it tick. There's no substitute for that.
+
+I strongly believe that the world would be a better place if everyone shared
+their knowledge (in all fields) and we all learned from each other. In some
+cases it's simply not practical, but more often than not I think people want
+to horde their knowledge and feel superior. Sure, that might be nice for your
+ego, but does it really make the world a happier, more beautiful place to
+live?
+
+[Apache]: http://apache.org/
+
+I Might Get Free Code!
+----------------------
+
+Well, probably not, but who knows? Maybe some developer has a lot of free time
+on his or her hands?
+
+Distributed version control systems like [Mercurial][] make it extremely easy
+to help out with open source projects. For example, if you were looking
+through my code and saw a bug that you wanted to fix, you could do the
+following:
+
+* Clone the repository to your own machine. * Fix the bug in that local copy,
+committing to your local repository as you go. * Go back to the website and
+click the "Pull Request" button. * I review the changes. * If I like them I
+press a button to merge them into the main repository.
+
+Once the changes are in the main repository I just run a single script to
+redeploy the site as usual and the changes are live. It's really an almost
+painless process. Compare that to something like Subversion or (ick) CVS:
+
+* Check out the repository to your own machine.
+* Fix the bug in that local copy, without committing (don't mess up!).
+* Create a patch using diff or something similar.
+* Email me the patch.
+* I review the changes.
+* If I like them I check out a fresh copy of the repository.
+* I apply the patch to this copy.
+* I merge the patch back into the main repository.
+
+It's much more difficult because I don't want to just give any anonymous
+person commit access to my repository.
+
+It Makes Me Fix My Damn Code
+----------------------------
+
+This is probably the most tangible and important benefit of my open sourcing
+this site. It forced me to rewrite parts of the code that weren't secure and
+do it the right way.
+
+Passwords stored in source control? Yeah, *definitely* a bad thing.
+
+Of course, it *was* kind of a pain in the ass to refactor a bunch of stuff.
+Really, though, the main problem I had was my own procrastination and going
+open source was a good nudge. Plus when I start work on another site I'll know
+how to do it right the first time.
+
+Aside from major security and privacy issues, it also gives me a big incentive
+to clean up my code and make it more elegant. Clean, elegant code makes me
+happy. It's less likely to have bugs (because there are fewer places for them
+to hide) and it's far easier to maintain in the long run.
+
+It's also simply more fun to read and work with.
+
+You Should Probably Try It
+--------------------------
+
+Obviously not all software is appropriate for open sourcing, but if you've got
+a pet project that you've been working and you think it might benefit from a
+few more sets of eyes, try it!
+
+You don't need to spend money or configure much of anything to share your
+code; sites like [BitBucket][] and [GitHub][] offer free hosting and great
+interfaces for repositories of open source code.
+
+If you have any questions or comments I'd love to hear them!
+
+[BitBucket]: http://bitbucket.org/
+[GitHub]: http://github.com/
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/01/site-redesign.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,45 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Site Redesign"
+    snip: "Yeah, I know.  Again."
+    created: 2009-01-11 17:58:23
+%}
+
+{% block article %}
+
+Well, I've redesigned the site again. This time it's all me. I built the site
+from the ground up with [Django][] and [Python][]. Why? Several reasons:
+
+* I already pay for hosting at [WebFaction][] for other sites so also paying [Squarespace][] for my personal one was too wasteful.
+* I wanted to practice designing another site with [Django][].
+* I wanted more flexibility than [Squarespace][] supports and I'm not afraid to get my hands dirty with code.
+
+If you want to know more about how I created the site, check out the site's
+[project page][].
+
+Moving over
+-----------
+
+I've tried to make transitioning to the new site as easy as possible. For
+example, I set up the urls so that links to the entries on the old blog will
+redirect to entries on the new one if they exist.
+
+Coming soon
+-----------
+
+I'm going to work on porting over more of the old blog entries in the next day
+or two. I don't want to bring them all over; just the best ones.
+
+I'm also going to implement an RSS feed that will encompass projects and blog
+entries.
+
+Let me know what you think!
+
+[Python]: http://python.org/
+[Django]: http://djangoproject.com/
+[WebFaction]: http://webfaction.com/
+[Squarespace]: http://www.squarespace.com/
+[project page]: /projects/stevelosh-com
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/02/how-and-why-i-dj.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,205 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "How &amp; Why I DJ"
+    snip: "I like playing music for dancers."
+    created: 2009-02-06 17:53:44
+%}
+
+{% block article %}
+
+I've been DJ'ing at swing and blues dances for a while now. It's extremely fun
+and rewarding. I've got a system that I use to keep myself sane while doing it
+and I felt like sharing. Let me know what you think!
+
+[TOC]
+
+## How I Started
+
+When I was just starting to get really interested in dancing I didn't think
+I'd want to DJ much. I thought it would be a lot of work and that I'd hate
+having to stay near a computer during a dance. It just didn't seem like very
+much fun.
+
+The only reason I began to try my hand at it was because we needed to have
+good music to play at RIT Swing Dance Club when my old roommates and I started
+teaching there. I wanted the other people to have a good time and hear the
+awesome music that we love dancing to. I figured that it didn't need to be a
+big deal; I'd just find some cool music and play it at club.
+
+Once I started, I realized that I really like being able to play great music
+for other people to dance to. It sounds cliche, but it really *is* rewarding.
+There's something special about having a kind of control over an entire dance
+floor.
+
+After I became comfortable DJ'ing at club it was only a matter of time before
+I started [signing up to DJ][ljdj] at [Lindy Jam][] and then playing music at
+our little blues parties. I love it. DJ'ing is good for me &mdash; it forces
+me to look for interesting new music and really *listen* to it to hear how it
+works. Really listening (without dancing) closely to swing or blues music is
+something that I don't think enough dancers do.
+
+## Where Do I Find Music?
+
+Most of the music I play comes from [eMusic][]. It's a great site &mdash; you
+pay $15 and get about 40 tracks per month. That's far cheaper than iTunes and
+it's all DRM-free mp3 files. They have a great collection of jazz and blues
+(and a lot of indie and classical music too). I highly recommend them if
+you're looking for some awesome music.
+
+Previously I've wanted nothing to do with iTunes because of the DRM.
+Thankfully Apple has announced that they've convinced the record labels to
+allow DRM-free downloads of everything. I'll still get most of my music from
+eMusic (it's cheaper) but if they don't have a song I want I'll definitely
+look on iTunes.
+
+As for CDs and vinyl, I do occasionally buy and rip some, but for the most
+part digital music is simply faster, easier, and cheaper to use.
+
+## Sorting My Music
+
+Over the past couple of years I've turned into a pretty organized person. If I
+don't have a good method of sorting and organizing my music I'll go crazy when
+I try to DJ. I've developed a way of organizing everything over the years I've
+been DJ'ing which seems to work pretty well for me.
+
+### "Danceable" Music
+
+The first thing I do when I download a new CD from eMusic is skim each track
+and decide if it's even remotely danceable. If it's got a beat I can dance to
+at all, it goes into my "Lindy & Blues" playlist in iTunes. I don't worry
+about how good the song is &mdash; the important part for me is getting the
+decent songs into that playlist so I don't forget about them.
+
+### Tempo
+
+My next step is tagging danceable songs with BPM (beats per minute)
+information. This is really nice to know when you're out at a dane and
+thinking: "I should play a song that's a bit faster than that last one."
+
+I've experimented with a couple of different methods in the past but they all
+seemed pretty cumbersome. The solution came in the form of this [Tempo
+Widget][] for my Mac's dashboard. Click the button on each beat, double click
+the numbers to save the BPM to the currently playing iTunes song.
+
+That's nice, but it's not enough for a nerd like me. The mouse is so slow;
+what I really needed was a way to use the keyboard for everything so I could
+fly through tagging my songs in less than 15 seconds each. I opened up the
+code for the widget and added a couple things. I can press any key on a beat
+instead of clicking the button, and I can hit Cmd+S to save the BPM to the
+iTunes song instead of double clicking the numbers.
+
+I also use [Quicksilver][] to add keyboard shortcuts to move to the
+next/previous song in iTunes. Now that I've got all that done, when I want to
+tag a bunch of new songs with BPMs I can do this:
+
+1. Start playing the first song and open up the dashboard.
+2. Press any key on each beat until I have a consistent BPM displaying.
+3. Press Cmd+S to save the BPM to the song.
+4. Press Cmd+Option+Ctrl+Right Arrow to move to the next song.
+5. Repeat steps 2-5 for each song.
+
+It usually takes me 15 seconds or less per song and saves me a ton of time (I
+have about 900 songs tagged with BPMs right now!). If you're interested in my
+modified version of the Tempo Widget let me know.
+
+### Rating (Smartly)
+
+Let's face it: some songs are better than others. Some songs are fun to dance
+to, but others almost *force* you out of your seat. I like to be able to
+glance at my playlist and have a rough idea of which *really awesome* songs
+I've got at a specific tempo.
+
+Some people might say: "You should know all of your music by heart and
+shouldn't need to rely on ratings." I disagree &mdash; maybe I'm just not as
+diligent in studying but there's no way I could remember every single song in
+my playlist. Of course you should know your music, but that doesn't mean you
+can't use whatever tools you like to make your DJ'ing even more effective.
+Ratings help me remember to play a song that I might otherwise have forgotten
+about and let me see what my options are if I really need a fantastic song
+*right now*.
+
+Unfortunately I didn't start rating my danceable songs until a month or two
+ago and so I'm only about halfway through. One thing that helps is iTunes'
+Smart Playlists. I can create a smart playlist that only shows me songs that
+are in my "Lindy & Blues" playlist but aren't yet rated.
+
+![Unrated Smart Playlist Screenshot](/site-media/storage/blog/2009-02-06-DJ/playlist-unrated.png "Unrated Smart Playlist")
+
+I have an iPod as well, so when I'm out and listening to my music I can set
+the rating right on the iPod. When I get back to my computer I plug in the
+iPod and it syncs the ratings back to iTunes for me.
+
+## At a Dance
+
+All of the steps I've talked about so far have one goal: to make playing great
+music at an actual dance easier.
+
+### Previewing
+
+I rarely preview songs before I play them; I know my collection pretty well and usually have a good idea whether or not a song will fit.  Still, it's definitely nice to be able to hear a song now and then.
+
+Some DJ's really love external sound cards which let you have two music
+players open on your machine; one plays the music going to the room speakers
+and the other plays into a set of headphones. I don't use this setup for a few
+reasons:
+
+* I can't be bothered to buy an external sound card.  I know, I'm lazy.
+* Computers are tricky, and adding another sound card into the mix makes things trickier.  Having another audio interface often causes some headaches when you're ready to DJ and no sound is coming out of one port because there's a configuration option messed up somewhere.
+* I don't trust myself.  I can easily see myself accidentally trying to preview on the music player that's going to the room.
+
+What do I do instead? I use my iPod. Sure, the interface isn't as easy to
+navigate as a music player on a laptop, but it doesn't cost any extra money (I
+have it anyway) and there's no chance of accidentally messing up the currently
+playing song.
+
+### Running Playlists
+
+Throughout the night as I decide which songs I want to play I put them in two
+separate lists. First they go into my "Short List" which is usually around
+five to ten songs that I think I'll want to play fairly soon. That gives me
+easy access to songs I'll probably play soon.
+
+The "Running" playlist is the one that's actually playing through the
+speakers. I usually have one or two songs queued up ahead of time in case I
+get distracted from my laptop for a bit.
+
+### Sorting on the Fly
+
+All the work I put into tagging and rating my music pays off when I'm actually
+trying to decide what to play next. When I'm looking through my collection my
+iTunes window will usually look like this (except for being slightly bigger
+and having the sidebar showing):
+
+![Sorted Danceable Playlist Screenshot](/site-media/storage/blog/2009-02-06-DJ/playlist-sorting.png "Sorted Danceable Playlist")
+
+I can use the search bar in the upper right if I'm looking for something
+specific. I can sort by BPM if I know I want a song at a rough tempo. The
+ratings draw my eyes to the songs that I love the most. The comments are there
+to remind me about songs that have long intro/outros, double timed sections,
+etc. Having all of that at my fingers makes it much easier for me to find
+exactly what I want and get it to the speakers.
+
+### And So...
+
+I wrote this because I wanted to share how and why I DJ for dancers. If you're
+a DJ, I hope I've given you a couple of ideas for new tricks to make your job
+easier. **Let me know what you think in the comments!**
+
+If you don't DJ but think you might want to, great! Please don't be scared off
+by my absurdly organized workflow &mdash; just because it works for me doesn't
+mean you have to do it. Find some good music and [sign up to DJ at Lindy
+Jam][ljdj]! If you think two hours is too long for you as when you're first
+learning to DJ just ask myself, Matt, Jesse, Mike or Beth if we'll share the
+night half & half with you. If you have any questions please let me know!
+
+
+[Lindy Jam]: http://lindyjam.com/
+[ljdj]: http://lindyjam.com/schedule/
+[eMusic]: http://emusic.com/
+[Quicksilver]: http://www.blacktree.com/
+[Tempo Widget]: http://mac.softpedia.com/get/Dashboard-Widgets/Music/Tempo-Widget.shtml
+
+
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/02/how-i-shoot-dances.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,308 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "How I Shoot Dances"
+    snip: "Slow shutter and flash."
+    created: 2009-02-09 18:04:36
+%}
+
+{% block article %}
+
+Last weekend [Gordon Webster][] came to Rochester, NY to play a dance at The
+Keg. It was awesome (of course) and everyone had a great time.
+
+I took a lot of photos during the course of the night (around 360 actually)
+and some of them turned out pretty nice. A few people have wondered how I got
+the look I did, so I decided to write a post about it.
+
+I'm assuming you know what basic terms like aperture and shutter speed mean.
+If not, look for a post over at [LindyBloggers][] fairly soon about shooting
+dances with a point-and-shoot camera.
+
+[Gordon Webster]: http://webster.suresong.com/
+[LindyBloggers]: http://lindybloggers.com/
+
+Shooting Dancers is Tough
+-------------------------
+
+One of the reasons I got into photography seriously was so that I could shoot
+dancers and musicians. I've since branched out and become interested in a lot
+of other aspects of photography, but dancing is a huge part of my life and
+photographing dancers is still something I absolutely love.
+
+I (like many others) thought that getting a DSLR would let me take awesome
+dancing photos with a bit of practice. Well, it's not that simple. Dances are
+one of the hardest things I shoot for a couple of reasons.
+
+### We Move
+
+Dancing, especially in a dance like Lindy Hop, involves a lot of movement. It
+makes focusing a huge pain unless you've got *really* good eyes. I don't. When
+I first started out the majority (at least 70%) of my dance photos were out of
+focus. It's much more difficult than shooting a still (or even slowly moving)
+target.
+
+Moving quickly also means you need a fast shutter speed if you want anything
+to be sharp. You can focus perfectly but that won't freeze any movement. This
+wouldn't be an issue if it wasn't for the second main problem.
+
+### The Lighting at Dances is Awful
+
+Seriously, it's terrible. It's always fairly dark to set the mood; you don't
+want to dance in a brightly lit place unless you're competing. To make matters
+worse, it's almost always ridiculously uneven. Part of the room with usually
+be two or three stops darker than the rest.
+
+Only shooting in one place helps, but is fairy boring. A lot of people will
+stay in the same general area for most of the night (damn cliques!) and so if
+you only shoot one section of the floor you'll miss a lot of people.
+
+What Doesn't Work (for Me (Usually))
+------------------------------------
+
+I've tried a couple of different techniques to overcome these problems. Some
+of them work in some situations but most of the time they leave me unhappy.
+
+<a href="http://www.flickr.com/photos/sjl7678/2449590741/" title="GirlJamSunday-5512 by Steve Losh, on Flickr"><img src="http://farm3.static.flickr.com/2076/2449590741_b47a5ced4c_m.jpg" width="161" height="240" alt="GirlJamSunday-5512" class="blog-photo-inline-right" /></a>
+
+### Fast Primes, High ISO
+
+The first remedy I turned to was buying a fast prime lens (Pentax 50mm f/1.4)
+so that it would let in more light. With that lens I would turn up the ISO to
+1600 or so to get even more sensitivity and hope for the best. This kind of
+works, but has some issues.
+
+#### The Good
+
+Shooting with a fast prime means I only have to carry one lens around and
+don't need to change it during the night. They're usually pretty light too, so
+they're easier to work with. 50mm is a nice focal length that lets you stand
+far enough away to not get kicked. You also don't need to annoy people with
+flash.
+
+The wide apertures let more light in so you can actually get some decently
+exposed photos at workable shutter speeds. The ISO isn't much of an problem as
+long as you expose the photo right (if you have to bring up the exposure more
+than a half stop in post it looks terrible).
+
+This solution really excels if you're shooting classes or workshops. The light
+there is usually much better than at actual dances but still not ideal. The
+wide apertures let you soak up all of that light and you can get some really
+nice photos. The example in this section was taken at Girl Jam last year
+during one of the classes with my 50mm.
+
+#### The Bad
+
+Focusing on moving dancers is hard enough at "normal" apertures; trying to
+nail the focus when you've only got six inches of depth of field at f/1.4 is
+*nearly fucking impossible*. Maybe other photographers are better at manually
+focusing or have amazing Canon/Nikon cameras that can focus on a black cat in
+a darkroom, but I'm not and I don't.
+
+The focal length of most fast primes is generally around 50mm. This isn't too
+bad, but I've grown to really love wide angle lenses. 50mm feels too far and
+detached for my taste. Yours may be different, so give it a try.
+
+<a href="http://www.flickr.com/photos/sjl7678/3256610463/" title="LindyJam-0095 by Steve Losh, on Flickr"><img src="http://farm4.static.flickr.com/3400/3256610463_5465877459_m.jpg" width="181" height="240" alt="LindyJam-0095" class="blog-photo-inline-right" /></a>
+
+### Bounced Flash, Max Sync Speed
+
+For a while I was adamant that I would never use flash. I figured it would be
+annoying and that the "unnatural" light from the flash would somehow look
+wrong. I avoided it for a while in favor of fast primes and "natural" light.
+
+Eventually I noticed that some other photographers shot with flash at dances
+and it didn't annoy me (while dancing) at all. I decided to give it a shot and
+see how it worked, especially since I was getting really into [Strobist][] and
+studio lighting at the time.
+
+[Strobist]: http://strobist.com/
+
+The basic idea is that you use an external flash (preferably off camera,
+synched with a cord or radio triggers) and bounce the light from the ceiling
+to get more even coverage. You set the aperture to something moderate like f/4
+or f/5.6 and the ISO fairly low. You turn the shutter speed down as low as it
+will go and still sync up and let the strobe do the hard work.
+
+#### The Good
+
+You get sharp photos! What's more, focusing is no longer something you will
+curse vehemently! When you're shooting at f/4 or f/5.6 you have a good amount
+of depth of field so the focus doesn't have to be absolutely perfect.
+
+The flash only lasts about 1/1000 of a second. No one moves much in that time,
+so you get perfectly sharp photos despite the movement.
+
+Now that you're not relying on wide apertures you can start using different
+focal lengths instead of sticking with the fast prime or two that you have.
+You could even use a zoom lens if you don't want to change lenses all the
+time.
+
+#### The Bad
+
+Bouncing from the ceiling is far, far better than keeping your flash on camera
+and pointing it straight at the subjects, but unless the room has obnoxiously
+high ceilings you're still going to get a lot of falloff towards the back of
+the room. You might not mind; it *does* help isolate the subjects from their
+surroundings but I found myself getting tired of it pretty quickly.
+
+You also have to carry a flash, sync cord or triggers, and extra batteries
+around which is kind of a pain. I don't mind, but if you like traveling light
+it could bother you.
+
+This section's example is one of the better results of this technique: Tango
+Cafe's ceilings are very high so the light is pretty even everywhere. High
+ceilings come at a price, however: you need more power from the flash to
+illuminate everything and so can't shoot as fast.
+
+Rethinking My Approach
+----------------------
+
+After using these two methods for a while I stopped and looked at my photos. I
+wasn't as happy with them as I would have liked. I sat down and asked myself:
+"Why is that?" The photos were exposed well and aside from the focusing
+mishaps were pretty sharp. What was missing?
+
+<a href="http://www.flickr.com/photos/sjl7678/299107896/" title="CIMG0171.JPG by Steve Losh, on Flickr"><img src="http://farm1.static.flickr.com/120/299107896_fbec7e2df7_m.jpg" width="240" height="155" alt="CIMG0171.JPG" class="blog-photo-inline-right" /></a>
+
+Eventually I came up with my answer: "Movement." Lindy Hop is very much about
+movement; it's one of the most important parts of the dance, maybe even *the*
+most important part. Getting tack sharp photos is great, but it's very hard to
+convey movement with them unless you're a much better photographer than I am.
+
+Most people are not photographers. Most dancers are also not photographers.
+The majority of Lindy Hoppers will take photos with small point-and-shoot
+cameras, *if* they can drag themselves away from dancing for a little while!
+
+The result is that we don't usually see many dance photos (because we're too
+busy dancing to take them) and the ones that we do see are usually blurry
+(because point and shoot cameras in their default modes are just not equipped
+to take sharp ones).
+
+<a href="http://www.flickr.com/photos/sjl7678/299107792/" title="CIMG0141.JPG by Steve Losh, on Flickr"><img src="http://farm1.static.flickr.com/118/299107792_0b4907245f_m.jpg" width="240" height="180" alt="CIMG0141.JPG" class="blog-photo-inline-right" /></a>
+
+Even with their flaws, *we love them* because they're the few photographic
+memories we have of some of the best nights of our lives.
+
+I wanted people to have the same feeling toward my photography as they do
+toward these informal snapshots. I wanted to capture the essence of these
+pictures we're so grateful for but use my experience to make something even
+better.
+
+I think I've finally figured out how.
+
+Using Everything
+----------------
+
+What evokes the feeling of movement in the point-and-shoot shots we look at? I
+think it's the blurriness. Our culture is used to looking at photographs and
+we know that "blurry photograph" usually means "moving subject" even if we're
+not always 100% clear on the physics of it.
+
+<a href="http://www.flickr.com/photos/sjl7678/3264591984/" title="GW-0453 by Steve Losh, on Flickr"><img src="http://farm1.static.flickr.com/250/3264591984_296047fb19_m.jpg" width="181" height="240" alt="GW-0453" class="blog-photo-inline-right" /></a>
+
+As photographers, we know what causes it. A subject moving while the shutter
+is open produces blur. Longer shutter speeds mean more blur. The little
+cameras that most of our memories come from simply don't have the aperture or
+sensitivity of our hefty DSLRs &ndash; all the poor little things can do is
+leave their shutters open a bit longer to get the light they need. That's why
+those cameras make blurry photos with their default settings.
+
+So how can I add some blurriness to my images? Use a slower shutter speed! I
+also want to keep some sharpness though, so the dancers are more recognizable.
+To do this, I use flash *at the same time*. The flash freezes the subjects
+enough to make them look good and then slow shutter speed and ambient light
+take over to add some movement.
+
+### The Technique
+
+What do you need to do this kind of thing? You can get by with any modern
+camera with a built-in flash, but to really have the flexibility that will
+make you happy you need the following things:
+
+* **A camera with a hot shoe or PC jack and manual controls**.  I use a Pentax K20D when I feel like lugging it out and a Canon G10 when I don't.
+* **An external flash.**  I use an $80 Vivitar 285hv which will work with anything, so no complaining about how your camera maker only sells $400 speedlights.
+* **A way to sync your flash with the camera.**  Some of the more expensive flashes have a wireless mode.  If not, you can buy radio triggers for $60 or so, or buy a sync cable for $15 to $20.  Trust me, having the flash *off* of the camera makes things so much easier.
+
+<a href="http://www.flickr.com/photos/sjl7678/3264540604/" title="GW-0290 by Steve Losh, on Flickr"><img src="http://farm1.static.flickr.com/195/3264540604_f4665b50e6_m.jpg" width="240" height="181" alt="GW-0290" class="blog-photo-inline-right" /></a>
+
+#### Step 1 &ndash; Dial in the Flash
+
+The first step to getting this look is to figure out what kind of exposure you
+need with *the flash alone* to get a well-lit shot.
+
+Turn your shutter speed down to the fastest it will sync (1/180th is usually
+fine) and use trial and error to find a nice combination of aperture, ISO and
+flash power. The actual numbers will depend on several things: how low the
+ceilings are, how powerful your flash is, etc.
+
+Aim for the lowest flash power you can while still keeping a good exposure, a
+narrow enough aperture to make focusing easy, and modest ISO noise. Once you
+figure it out you can probably keep those settings for the rest of the night,
+unless the ceilings are higher on one side of the room or something else
+equally annoying.
+
+#### Step 2 &ndash; Dial in the Ambient
+
+This is the step that adds the movement. First, tone down your flash-only
+exposure by a half or whole stop. Do this by reducing the ISO, aperture, or
+flash power; any of those is fine.
+
+Now that your photo is underexposed, turn off the flash. It will probably be
+completely black now. *Do not touch the ISO or aperture to fix this.* Lengthen
+the shutter speed until you're about two stops underexposed; it will be blurry
+and dark as hell but this is what you want right now.
+
+<a href="http://www.flickr.com/photos/sjl7678/3263800481/" title="GW-0580 by Steve Losh, on Flickr"><img src="http://farm1.static.flickr.com/196/3263800481_9ebf0a47f3_m.jpg" width="240" height="181" alt="GW-0580" class="blog-photo-inline-right" /></a>
+
+#### Step 3 &ndash; Combine and Adjust
+
+Turn the flash back on. Do not touch any other settings &ndash; flip the
+switch on the flash and start shooting. This will let the flash illuminate the
+subjects (because you dialed in the power, ISO and aperture before and haven't
+changed them) and the ambient fill in and add movement (because you adjusted
+the shutter speed).
+
+Your first few shots will probably be underexposed or overexposed and have too
+much or too little blur. Don't worry, it always takes me at least a half hour
+to start taking decent photos this way. You really need to play with the
+settings as you go to find out what's going to work for the lighting *that
+night*.
+
+#### Things to Watch Out For
+
+There are a couple of tricky parts to this style of shooting that I'll
+mention. First I'll talk about the typical problems you'll see right away.
+More than one of these certainly might apply; fix them one at a time.
+
+<a href="http://www.flickr.com/photos/sjl7678/3263819663/" title="GW-0656 by Steve Losh, on Flickr"><img src="http://farm1.static.flickr.com/192/3263819663_4f97c18da4_m.jpg" width="181" height="240" alt="GW-0656" class="blog-photo-inline-right" /></a>
+
+* **If the background is dark or there is not enough blur,** you need to use a longer shutter speed to let more ambient light in.
+* **If the dancers are not sharp enough,** you need *more* flash power.  Turn it up a little bit at a time.
+* **If people's shirts, faces and limbs are overexposed *and not blurry*,** you need to turn down the flash.  Bring it down a bit by reducing the power, narrowing the aperture or reducing the ISO.
+* **If shirts, faces and limbs are overexposed *and blurry*,** you need to shorten the shutter speed to let less ambient light in.
+
+I'm warning you now, fixing one of these will probably fuck something else up.
+It can be really infuriating, but if you slow down, stay calm and think
+through it logically you'll be able to narrow it down and figure out what you
+need. It's a really good feeling when you finally nail it.
+
+There are two other tricky problems that I'm still working on myself:
+
+* **Dances are unevenly lit.**  When you walk over to the other side of the room to shoot, you'll have to adjust the shutter speed to compensate for the different amount of ambient light.  You really only have a range of about half a stop where the ambient gives you the right amount of blur, so you have to be careful and stay on your toes.
+* **Watch where you bounce.**  In rooms with low ceilings, where you point the flash on the ceiling has a huge effect on the lighting.  You need to be conscious of what part of the ceiling you're bouncing from to get good results.
+
+Good Luck!
+----------
+
+I hope this post helped you out. Even if you hate how my photos look and don't
+want to make anything like them, at least it will show you what *not* to do.
+I'd love to hear comments or advice on what you like or don't like, and what I
+could do better. If you've got questions I'll do my best to answer them too!
+
+Now go dance, have fun, and make beautiful photographs so we can all remember
+the fantastic events we make happen!
+
+<a href="http://www.flickr.com/photos/sjl7678/3263760493/" title="GW-0438 by Steve Losh, on Flickr"><img src="http://farm1.static.flickr.com/196/3263760493_08c525cfe7.jpg" width="500" height="377" alt="GW-0438" /></a>
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/03/candy-colored-terminal.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,95 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Candy Colored Terminal"
+    snip: "Better colors for the OS X Terminal."
+    created: 2009-03-18 18:26:28
+%}
+
+{% block article %}
+
+Yesterday I wrote a blog post about [adding Mercurial information to your bash
+prompt](/blog/entry/2009/3/17/mercurial-bash-prompts/). Almost all of the
+comments on that entry so far have been asking for the colors I used in the
+Terminal screenshots, so that's what this post is for.
+
+The first section of this entry will be able overcoming the limitations of the
+OS X Terminal application. Skip it if you're using another (better) terminal
+application.
+
+The OS X Terminal and Colors
+----------------------------
+
+OS X's Terminal doesn't support 256-color mode. I have no idea why. Apple, if
+you're reading, *please fix this*. Because of this, if you want to make the
+colors prettier you've only got the 16 ANSI colors to work with.
+
+Once again, Apple fails hard with Terminal.app. You can't change the 16 ANSI
+colors -- you can only change the default text color and background.
+Seriously, Apple, what the hell?
+
+To fix this, you'll need to install [SIMBL][] and [TerminalColors][]. Follow
+the instructions on those pages and be sure to restart Terminal once you've
+finished. Now you can change the ANSI colors be hitting the "More" button
+under the text color settings.
+
+[SIMBL]: http://www.culater.net/software/SIMBL/SIMBL.php
+[TerminalColors]: http://ciaranwal.sh/2007/11/01/customising-colours-in-leopard-terminal
+
+Picking Some Colors
+-------------------
+
+Now that we've beaten Terminal.app into compliance, it's time to pick some
+pretty colors. I love the [Monokai][] color scheme for [TextMate][] and so I
+based my choices on that. Here's what it looks like:
+
+![Screenshot of my Terminal, with colors.](/site-media/storage/blog/2009-03-18-terminal/terminal-colors.png "My Terminal colors.")
+
+[Monokai]: http://www.monokai.nl/blog/2006/07/15/textmate-color-theme/
+[TextMate]: http://macromates.com/
+
+Here are the RGB values I'm using:
+
+* Black: 0, 0, 0
+* Red: 229, 34, 34
+* Green: 166, 227, 45
+* Yellow: 252, 149, 30
+* Blue: 196, 141, 255
+* Magenta: 250, 37, 115
+* Cyan: 103, 217, 240
+* White: 242, 242, 242
+
+The window background is just set to plain old 0, 0, 0 with a 95% opacity.
+
+Not all of the colors match the names: "blue" is actually more of a purple,
+and "yellow" is much more orange. That doesn't really matter much though
+because they're different enough from each other to still be useful.
+
+Now that the colors are set up you can use them in the normal way. Check out
+[this guide][] if you don't know how to do that. Here's the full code for my
+bash prompt:
+
+**UPDATE:** I've cleaned up the code a lot thanks to the kind folks in #bash
+on freenode who helped set me straight on bash quoting and escaping. I've also
+switched to using my [hg-prompt extension](/projects/hg-prompt/) for the
+repository information.
+
+[this guide]: http://www.ibm.com/developerworks/linux/library/l-tip-prompt/
+
+    #!bash
+    D=$'\e[37;40m'
+    PINK=$'\e[35;40m'
+    GREEN=$'\e[32;40m'
+    ORANGE=$'\e[33;40m'
+    
+    hg_ps1() {
+        hg prompt "{${D} on ${PINK}{branch}}{${D} at ${ORANGE}{bookmark}}{${GREEN}{status}}" 2> /dev/null
+    }
+    
+    export PS1='\n${PINK}\u ${D}at ${ORANGE}\h ${D}in ${GREEN}\w$(hg_ps1)\
+    ${D}\n$ '
+
+I hope this helps! If you'd like to share your color schemes or tell me how to
+make the code for my prompt a bit less ugly, please comment!
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/03/mercurial-bash-prompts.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,184 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Mercurial Bash Prompts"
+    snip: "Always know where you are."
+    created: 2009-03-17 21:34:55
+%}
+
+{% block article %}
+
+I've been spending a lot of time in the Terminal lately. I use bash, and it
+lets you configure the prompt pretty much however you want. I won't go into
+how to do the most basic configuration here - if you want to get up to speed
+check out this [guide][].
+
+In this post I'm just going to talk about one simple addition that I
+personally find very helpful: displaying the current branch of a [Mercurial][]
+repository.
+
+Update: the hg-prompt Extension
+---------------
+
+I swear, this is the last time I'm updating this entry. I went ahead and made
+an extension for Mercurial called
+[hg-prompt](http://stevelosh.com/projects/hg-prompt/) that does everything
+much more elegantly. **Use that instead!**
+
+[guide]: http://www.ibm.com/developerworks/linux/library/l-tip-prompt/
+[Mercurial]: http://www.selenic.com/mercurial/wiki/
+[git version]: http://gist.github.com/31631
+
+My Starting Point
+-----------------
+
+Here's what my prompt looked like a couple of days ago:
+
+![My bash prompt without the branch displayed](/site-media/storage/blog/2009-03-17-prompt/prompt-without-branch.png "My bash prompt without the branch displayed.")
+
+Here's the code in my `.bashrc` file to create it. I've stripped out the color
+information to save space.
+
+    #!bash
+    export PS1='\n\u at \h in \w\n$ '
+
+I use the same prompt on every computer I work with, so with this prompt I can
+see which user I'm logged in as, which machine I'm on, and where in the
+filesystem I am. It's a lot of useful information at a glance but doesn't seem
+too cluttered.
+
+I have a linebreak in there because the filesystem path can get pretty long.
+If I kept it all on one line most of my commands would be wrapped around
+anyway, which I find harder to read.
+
+Adding the Mercurial Branch
+---------------------------
+
+I use Mercurial for version control, and I use branches quite a bit when I'm
+developing. One problem with this is that it's easy to forget which branch I'm
+on at a given moment. I *could* just use `hg branch` to find out, but that
+gets tedious to type, even when aliased to something like `hb`.
+
+A few days ago I got the idea that I could just display the current branch on
+my prompt whenever I'm in a directory that's part of a repository. Here's what
+my prompt looks like now:
+
+![My bash prompt with the branch displayed](/site-media/storage/blog/2009-03-17-prompt/prompt-with-branch.png "My bash prompt with the branch displayed.")
+
+And here's the code in my `.bashrc` that does it:
+
+    #!bash
+    hg_in_repo() {
+        hg branch 2> /dev/null | awk '{print "on "}'
+    }
+
+    hg_branch() {
+        hg branch 2> /dev/null | awk '{print $1}'
+    }
+
+    export PS1='\n\u at \h in \w $(hg_in_repo)$(hg_branch)\n$ '
+
+The `on branchname` piece is only displayed when you're in a directory that's
+part of a Mercurial repository.
+
+I've split it up into two separate functions because I wanted to have `on` and
+`branchname` displayed in two different colors. I couldn't seem to include the
+color codes in the awk command, so I split it up and put the colors in the
+export statement with the rest of them. If you don't care about colors (or
+don't mind having both words the same color) you can just collapse it into one
+function.
+
+Updated: Is It Dirty?
+---------------------
+
+After I posted this entry Matt Kemp commented with a link to a [git
+version][]. One feature that version has is a simple indicator of whether or
+not the repository you're in is dirty. I ported it to Mercurial and here's the
+result:
+
+![My bash prompt with the branch and dirty indicator displayed](/site-media/storage/blog/2009-03-17-prompt/prompt-with-dirty.png "My bash prompt with the branch and dirty indicator displayed.")
+
+And the code in `.bashrc`:
+
+    #!bash
+    hg_dirty() {
+        hg status --no-color 2> /dev/null \
+        | awk '$1 == "?" { print "?" } $1 != "?" { print "!" }' \
+        | sort | uniq | head -c1
+    }
+    
+    hg_in_repo() {
+        [[ `hg branch 2> /dev/null` ]] && echo 'on '
+    }
+
+    hg_branch() {
+        hg branch 2> /dev/null
+    }
+
+    export PS1='\n\u at \h in \w $(hg_in_repo)$(hg_branch)$(hg_dirty)\n$ '
+
+This gives you a `?` after the branch when there are untracked files (and
+*only* untracked files), and a `!` if there are any modified, tracked files.
+
+Updated: Bookmarks Too!
+----------------
+
+I've added another piece to show bookmarks as well. I've also figured out how
+to add colors directly in the functions, so here's the (much nicer) updated
+code all at once:
+
+    #!bash
+    DEFAULT="[37;40m"
+    PINK="[35;40m"
+    GREEN="[32;40m"
+    ORANGE="[33;40m"
+    
+    hg_dirty() {
+        hg status --no-color 2> /dev/null \
+        | awk '$1 == "?" { unknown = 1 } 
+               $1 != "?" { changed = 1 }
+               END {
+                 if (changed) printf "!"
+                 else if (unknown) printf "?" 
+               }'
+    }
+    
+    hg_branch() {
+        hg branch 2> /dev/null | \
+            awk '{ printf "\033[37;0m on \033[35;40m" $1 }'
+        hg bookmarks 2> /dev/null | \
+            awk '/\*/ { printf "\033[37;0m at \033[33;40m" $2 }'
+    }
+    
+    export PS1='\n\e${PINK}\u \
+    \e${DEFAULT}at \e${ORANGE}\h \
+    \e${DEFAULT}in \e${GREEN}\w\
+    $(hg_branch)\e${GREEN}$(hg_dirty)\
+    \e${DEFAULT}\n$ '
+
+These are some pretty simple changes but they help keep me sane. One thing to
+be aware of: if you use all of these it does slow down the rendering of the
+prompt by a tiny, but noticeable, amount. I'm not the strongest bash scripter,
+so if there's a better way to do this (or a way that will make it faster and
+reduce the delay) please let me know!
+
+**UPDATE:** Matt Kemp posted a link to a [git version][] of this below. If you
+use git, check it out! One thing that version has that I didn't think of is an
+indicator of whether the repository is dirty (has uncommitted changes). I'm
+going to go ahead and steal that idea for my prompt too.
+
+**UPDATE:** By request, I've written [an entry about the
+colors](/blog/entry/2009/3/18/candy-colored-terminal/).
+
+**UPDATE:** Kevin Bullock pointed out that the Python interpreter needed to be
+started a bunch of times which will degrade performance. I've changed up the
+"dirty" code a bit to reduce the number of interpreters needed. It's still not
+as efficient as his version, but I think it's about as good as I'm going to
+get if I want separate colors for the pieces and don't want to rely on an
+external script.
+
+**FINAL UPDATE:** I made an extension for Mercurial called
+[hg-prompt](http://stevelosh.com/projects/hg-prompt/) that does everything
+much more elegantly. **Use that instead!**
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/04/why-people-dont-like-metal.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,130 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "Why People Don’t Like Metal"
+    snip: "It’s probably not what you think."
+    created: 2009-04-02 22:32:27
+%}
+
+{% block article %}
+
+I don't think I've ever written a blog entry strictly about music. Usually
+I'll reference it when I write about dancing, but today I just want to talk
+about music. In particular, metal.
+
+"Metal" can refer to a lot of music. For this post I'm referring to the newer
+forms of metal that sprung up in the past decade or so. One example of this is
+[Should Have Stayed in the
+Shallows](http://www.youtube.com/watch?v=hmkLQRp8htY) by [Fear Before (the
+March of Flames)](http://www.fearbefore.net/). I know there are many, many
+more bands out there but this one song is a good sample of what I want to talk
+about.
+
+"I Don't Like all the Screaming"
+------
+
+If you play a metal song for someone that doesn't usually listen to the genre,
+this is probably the first thing you'll hear. There might be a mention of
+"everything is so loud" but almost without fail the screaming is what seems to
+turn people off. Why is that?
+
+The vocals of a song are usually the most noticeable part, especially for
+nonmusicians. Most people who don't play an instrument don't have the
+background to absorb and appreciate complicated instrumental work in any kind
+of music, but *everyone has vocal cords*. Everyone can appreciate speech and
+singing at some level.
+
+So what is it about screaming that most people don't like? If you ask them,
+you'll get an answer, but I don't think it's the correct one.
+
+"I Can't Understand the Words"
+-----
+
+This is what you'll usually hear when you press the issue. It seems reasonable
+-- the lyrics to most metal bands are indecipherable without a written copy,
+even to people that love them. Surely this is the problem?
+
+I don't think it is. To get at the *real* issue, I usually respond with one
+more question:
+
+**Do you enjoy any bands whose vocalist sings in a language you don't know?**
+
+I've never had anyone tell me: "I can't stand *any* music not in my own
+language." I'm sure there are some out there that feel that way, but I think
+they would be in the minority. I've met plenty of people that enjoy hearing
+[Sigur Rós](http://www.sigur-ros.co.uk/) and I'm fairly certain that *exactly
+none of them* speak Icelandic fluently. Many don't even pronounce the name
+correctly.
+
+If people enjoy listening to music with vocals in a language they don't
+understand, then their dislike of metal must not stem purely from
+unintelligible lyrics. What could it come from?
+
+Timbre
+------
+
+Here's one idea: many people are put off by the
+[timbre](http://en.wikipedia.org/wiki/Timbre) of a metal band.
+
+Timbre usually refers to the quality of a musical sound or note. It's what
+makes an E on a guitar sound different than an E on a cello, even if it's the
+same pitch. It's how you can tell your mother's voice from your friend's
+voice, even if she speaks at the same frequency.
+
+A concept I first came across when reading [This Is Your Brain On
+Music](http://www.amazon.com/This-Your-Brain-Music-Obsession/dp/0452288525/)
+is "the timbre of a band as a whole." The idea of timbre can be expanded to
+neatly describe why two bands playing the same song in the same key can sound
+*completely* different. The instruments of the band each contribute their own
+sound and when taken together you have a timbre just as unique as a particular
+instrument's.
+
+Metal bands each have their own timbre, but they're all related -- that's what
+makes them into a genre. A screaming vocalist is an extremely distinct element
+of this that isn't really found anywhere else. Perhaps the answer to "why do
+people dislike metal?" is that they simply don't enjoy the timbre, just as
+some people don't enjoy violins or saxophones.
+
+Lack of Musical Background
+-----
+
+This is another possible answer. As I mentioned before, everyone has vocal
+cords. Everyone can relate to a singer through the words they're singing. Even
+if the words are in a different language they can still relate to the act of
+singing. Not everyone knows how to sing well, but I believe you'd be hard
+pressed to find someone that has never sung in the shower or somewhere just as
+private.
+
+Very few people can (or want to) relate to screaming. Screaming is something
+we usually do only when threatened or angry, which is hopefully a minority of
+our lives. So once the vocalist is screaming constantly, people that don't
+enjoy metal no longer have the element they're most used to focusing on.
+
+What's left? If you can't understand the words, the voice becomes another
+instrument instead of something "special." Many people simply haven't ever
+tried listening to and appreciating purely instrumental music and so they lose
+interest.
+
+What Can We Do?
+-----
+
+I'm sure I haven't completely nailed down the reasons why people don't enjoy
+metal. It's almost certainly a combination of quite a few things. But if
+someone is genuinely interested in learning more about metal and about why
+people like it -- perhaps a close friend listens and they'd like to know more
+-- I think there's two things they can do that may help.
+
+**Think of the vocals as another instrument, and listen to how they interact
+with the rest of the band.**
+
+Admittedly, there's a lot of really terrible metal out there. As the genre has
+expanded in popularity a lot of "musicians" (barely) have jumped in and
+created bands no more musically meaningful than the average pop singer. It's
+easy to come across this and dismiss the whole genre as a bunch of untalented
+hacks.
+
+Word of mouth is probably the best way to pick out the good from the bad. If
+you look hard enough you can find some amazing music that you might grow to
+love and appreciate.
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/05/what-i-hate-about-mercurial.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,228 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "What I Hate About Mercurial"
+    snip: "Hg, I love you, but sometimes you bring me down."
+    created: 2009-05-29 19:51:05
+%}
+
+{% block article %}
+
+This entry was inspired by [Jacob Kaplan-Moss][JKM], who was inspired by
+[Titus][], who was inspired by [brian d foy][BDF]. The premise is that you
+can't really claim to know much about a piece of software until you can name a
+few things you hate about it.
+
+[JKM]: http://jacobian.org/writing/hate-python/
+[Titus]: http://ivory.idyll.org/blog/mar-07/five-things-I-hate-about-python
+[BDF]: http://use.perl.org/~brian_d_foy/journal/32556?from=rss
+
+Jacob and Titus talked about Python, and so have a bunch of other people, so I
+figured I'd write about something a bit different:
+[Mercurial](http://selenic.com/mercurial).
+
+I love Mercurial to death, but there *are* a few things about it that annoy
+me. Here they are, in no particular order.
+
+[TOC]
+
+Configuration Through a Textfile
+--------------------------------
+
+This is one of the things that [git](http://git-scm.com/) people seem to like
+to [bring up](http://jointheconversation.org/2008/11/24/on-mercurial.html):
+"It doesn't have a command to set your username and email and such? Lame."
+
+I personally don't mind editing a text file -- `vim ~/.hgrc` really isn't that
+hard to type and the format is simple enough that you get the hang of it in
+about ten seconds. It forces you to know *where* the config file is, which is
+nice when the magic "Oh man, I could put my config files under *version
+control*!" moment strikes.
+
+That said, this is on the list because I'd like to see a command to edit some
+of the common options just so people will *stop complaining* about something
+so trivial.
+
+"hg rm" is a Confusing Mess
+---------------------------
+
+Here's part of the help for the `hg rm` command:
+
+> This only removes files from the current branch, not from the entire
+> project history. -A can be used to remove only files that have already
+> been deleted, -f can be used to force deletion, and -Af can be used
+> to remove files from the next revision without deleting them.
+
+What the hell? If `-A` won't remove files that are still present, and `-f`
+forces the files to be deleted, why the fuck does combining them mean *the
+exact opposite of both*?
+
+I had to look up the syntax every single time I wanted to use this command,
+until I added this alias to my `~/.hgrc`:
+
+    [alias]
+    untrack = rm -Af
+
+Now I can use `hg untrack whatever.py` to stop tracking a file.
+
+Addremove Can Track Renames But Won't Unless You Ask It Really Nicely
+---------------------------------------------------------------------
+
+It took me a while to realize this, but Mercurial can actually record file
+renames -- not just separate adds and removes -- when using `hg addremove`.
+Here's what happens when you move a file and then use `hg addremove` normally
+to have Mercurial track the changes.
+
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ ls
+    total 16
+    -rw-r--r--  1 sjl    14B May 29 20:12 a
+    -rw-r--r--  1 sjl    12B May 29 20:12 b
+    
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ mv b c
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg addremove
+    removing b
+    adding c
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg diff
+    diff --git a/b b/b
+    deleted file mode 100644
+    --- a/b
+    +++ /dev/null
+    @@ -1,1 +0,0 @@
+    -To you too!
+    diff --git a/c b/c
+    new file mode 100644
+    --- /dev/null
+    +++ b/c
+    @@ -0,0 +1,1 @@
+    +To you too!
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg commit -m 'Normal addremove.'
+    
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ 
+
+Now watch what happens when we tell Mercurial to detect renames when using `hg
+addremove`:
+
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ ls
+    total 16
+    -rw-r--r--  1 sjl    14B May 29 20:12 a
+    -rw-r--r--  1 sjl    12B May 29 20:12 c
+    
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ mv c b
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg addremove --similarity 100
+    adding b
+    removing c
+    recording removal of c as rename to b (100% similar)
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg diff
+    diff --git a/c b/b
+    rename from c
+    rename to b
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg commit -m 'This time with rename detection.'
+    
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ 
+
+This time it notices the rename, and records it. The diff is far, far easier
+to read, and if a branch is merged in where someone else changed that file,
+the changes will follow it over.
+
+The `--similarity` option is a percentage. I have an entry in my `~/.hgrc`
+file to default that to 100, which means that renames will only be
+automatically detected if the files are *identical*. It's safer, but might not
+always catch everything.
+
+I wish I had known this earlier or that Mercurial defaulted to 100% to catch
+the obvious renames.
+
+And yes, I realize I could use `hg rename` to rename it and it *would* get
+recorded, but usually I'm moving files by some other method and using `hg
+addremove` to clean up later.
+
+Now, while we're on the topic...
+
+Why the Hell Does Status Not Show Renames?
+------------------------------------------
+
+Assuming they're recorded, I wish `hg status` would show that a file has been
+renamed. Here's what we get instead:
+
+    sjl at ecgtheow in ~/Desktop/test on default 
+    $ hg rename b c
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg stat
+    A c
+    R b
+    
+    sjl at ecgtheow in ~/Desktop/test on default! 
+    $ hg diff
+    diff --git a/b b/c
+    rename from b
+    rename to c
+
+No, `hg status`, it clearly *wasn't* an add and a remove, according to `hg
+diff`. Why doesn't `hg status` have a separate character for "renamed" files
+so we can tell them apart?
+
+Get Git Out of My Mercurial
+---------------------------
+
+I *hate* that half of Mercurial's commands need a `--git` option to be really
+useful. Is there any reason not to make this the default format and have a
+`--useless` option for backwards compatibility?
+
+I always add it to the defaults in my `~/.hgrc` but it makes me feel kind of
+dirty when I do. It adds a bunch of unnecessary lines to the config file and
+confuses new people.
+
+BitBucket Could Be Prettier
+---------------------------
+
+Don't get me wrong, [BitBucket](http://bitbucket.org/) is an awesome site, but
+compared to [GitHub](http://github.com/) it looks a bit dull and unappealing.
+
+It's definitely more usable (how the hell do I view a graph of all
+branches/merges of a given repository on GitHub?) but there's something about
+GitHub's design that just makes it pop.
+
+Mercurial's Site Could Be *Much* Prettier
+-----------------------------------------
+
+Mercurial's site is ugly. Very ugly. It seems strange to me that the ugly
+version control system (git) has a fairly good-looking site while the much
+more elegant Mercurial has something that looks so boring and dated.
+
+I know, [mercurial-scm.org](http://mercurial-scm.org/) aims to fix this. Thank
+you from the bottom of my heart but please, hurry. The wiki is hurting my
+eyes.
+
+But Hey, at Least It's Not Git!
+--------------------------------
+
+All of those things annoy me, but they're small problems compared to the
+revulsion I get when I try to use git every so often.
+
+Maybe that would be a good topic for another entry. At the very least it'll
+probably get me a ton of pageviews and comments saying: "Git's changed, man!
+It's not like it used to be, it's totally intuitive now! You just gotta learn
+how it stores the data!"
+
+I learned, and I'll still take Mercurial despite the small annoyances.
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/06/how-to-contribute-to-mercurial.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,367 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "How to Contribute to Mercurial"
+    snip: "Ten minutes of setup will make it easier."
+    created: 2009-06-01 20:09:44
+%}
+
+{% block article %}
+
+After my last post on [What I Hate About Mercurial][hate], seydar commented
+that I should contribute a patch to add untrack/forget functionality. I
+decided to take the advice, stop being lazy and write one.
+
+It's a very, very simple change and I'm not sure if it will even make it into
+the core repository, but even so it gave me a chance to figure out how to set
+up a decent development environment for hacking on Mercurial. I figured that
+other people might find that information useful so I decided to write this.
+
+[hate]: http://stevelosh.com/blog/entry/2009/5/29/what-i-hate-about-mercurial/
+
+[TOC]
+
+About This Guide
+----------------
+
+This is meant to be a guide to get yourself set up to work on Mercurial's code
+base and contribute your work back to the community. It's *not* a guide for
+actually working on the code.
+
+I'm going to go ahead and assume a few (small) things:
+
+1. You're running OS X or some form of Linux.  If you're using Windows, I'm sorry, but I just don't use it enough to really help.
+2. You've got [Python][] installed.
+3. You've got a copy of Mercurial installed in some way (MacPorts, apt-get, source, etc).
+4. You're familiar with (and have clients for) IRC and email.
+
+If those things are true, let's get started. The entire process should take
+between 15 and 45 minutes, depending on how comfortable you are with bash,
+Python, and Mercurial itself.
+
+[Python]: http://python.org/
+
+Join the Community
+------------------
+
+The first step to contributing is to join the community. Things will probably
+go more smoothly if other developers have seen your name before and those
+other developers are a great resource if you get stuck.
+
+Join the [#mercurial channel on Freenode][irc]. A lot of other Mercurial
+developers hang out in there and it's a good place to go if you want some
+really quick feedback. Take a few minutes and [register your nick][register]
+on Freenode, just because it's a good thing to do.
+
+You should also [subscribe][] to the Mercurial development [mailing list][].
+That's where you're going to be sending your work, so it's good to start
+getting an idea of how people use the list as soon as possible.
+
+[irc]: irc://irc.freenode.net/#mercurial
+[register]: http://freenode.net/faq.shtml#userregistration
+[subscribe]: http://www.selenic.com/mailman/listinfo/mercurial-devel/
+[mailing list]: http://www.selenic.com/pipermail/mercurial-devel/
+
+Grab the Source
+---------------
+
+Now you'll want to grab the Mercurial source code so you can start changing
+it. The repository you almost certainly want to clone is the [crew
+repository][].
+
+Several people (listed [here][crew members]) have write access to this and
+it's where most changes go before they're pulled into the main Mercurial
+repositories. Your want your changes to apply cleanly to the tip of crew if
+you want them to have the best chance of being accepted.
+
+Go ahead and clone it somewhere on your machine (replace `hg-crew` if you
+prefer a different name for the folder):
+
+    hg clone http://hg.intevation.org/mercurial/crew hg-crew
+
+It's going to take a little while. Mercurial might be fast but its repository
+has over 8,600 changesets. While you're waiting you can move on to the next
+step.
+
+[crew repository]: http://hg.intevation.org/mercurial/crew
+[crew members]: http://www.selenic.com/mercurial/wiki/CrewRepository
+
+Set Up virtualenv
+-----------------
+
+This might not seem like it's necessary, but trust me, it's a good thing to
+do. It will make things easier down the road, I promise.
+
+No, *really*, take ten minutes and do this. You'll thank me.
+
+[virtualenv][] is a tool that lets you create separate Python development
+environments that are isolated from each other. The packages and binaries for
+one won't contaminate the others. It will make testing our work on Mercurial
+painless.
+
+Open a new terminal window while the crew repository is busy cloning. Install
+virtualenv in the usual Python fashion:
+
+    sudo easy_install virtualenv
+
+Now install the [virtualenvwrapper][] tool:
+
+    sudo easy_install virtualenvwrapper
+
+This is a nifty little shell script that makes working with virtual
+environments much more pleasant. Before you can use it, you'll need to source
+it into your `~/.bashrc` or `~/.bash_profile` file, as well as choose a place
+to stick the environments themselves:
+
+    export WORKON_HOME=$HOME/lib/virtualenvs
+    source /(path to python)/bin/virtualenvwrapper_bashrc
+
+As you can see, I prefer to put the `virtualenvs` folder inside my `~/lib`
+folder. You can change that to any place you like.
+
+You'll also need to replace the `(path to python)` with the actual path to
+wherever Python is installed on your system. If you're not sure, here's a
+simple, slow, and horribly inefficient but effective command to figure it out:
+
+    find / -name 'virtualenvwrapper_bashrc' 2> /dev/null
+
+Once you've got the necessary lines in your `~/.bashrc` you can close that
+terminal window.
+
+[virtualenv]: http://pypi.python.org/pypi/virtualenv
+[virtualenvwrapper]: http://www.doughellmann.com/projects/virtualenvwrapper/
+
+Set Up A Public Repository
+--------------------------
+
+This isn't strictly required, but it's polite and only takes a minute or two.
+If you've already got a method of sharing your repositories (using hgwebdir
+with your website, for example) go ahead and use that.
+
+If not, head over to [BitBucket][], sign up for an account if you don't
+already have one (it's free), and create a new public repository there. I've
+named mine [hg-crew-sjl][] to be explicit about what it contains, but that's
+not terribly important.
+
+Why bother doing this when you're just going to email your work anyway? Some
+people (myself included) find it easier to pull changes from another
+repository than to apply them from emails. It also gets your changes out into
+a public place so other developers can view and modify *your* modifications.
+
+It's also nice to have an easily accessible clone of your personal repository
+if you're not at your own machine and want to do some more work.
+
+[BitBucket]: http://bitbucket.org/
+[hg-crew-sjl]: http://bitbucket.org/sjl/hg-crew-sjl/
+
+Set Up Your Local Clone
+-----------------------
+
+By now the crew repository should be finished cloning to your local machine.
+The first thing we want to do is set up the paths so we can push and pull
+easily. Modify the `.hg/hgrc` file inside that repository (*not* your
+`~/.hgrc` file!) to look like this:
+
+    [paths]
+    default = http://bitbucket.org/(username)/(repo name)/
+    crew = http://hg.intevation.org/mercurial/crew
+
+Replace `(username)` with your BitBucket username and `(repo name)` with the
+name of the BitBucket repository, obviously.
+
+Now you can run `hg push` to push any changes you commit locally to your
+public BitBucket repository, and `hg pull crew` to grab new changes from the
+crew repository.
+
+Build Mercurial
+---------------
+
+Make sure you're in your local crew repository, and run:
+
+    make local
+
+This will build Mercurial from the source files. It should finish fairly
+quickly. Once that's done, run the tests to make sure everything is working
+correctly:
+
+    make tests
+
+Those will take a long time to run. While you wait, move on to the next step.
+
+Create a Virtual Environment for Mercurial Development
+------------------------------------------------------
+
+While the test suite is running you're going to make a new virtual environment
+to use for testing your changes to Mercurial. First you need to create it, so
+open up a new terminal window and run:
+
+    mkvirtualenv hg-dev
+
+You can name it something else if you don't like `hg-dev`. Notice how your
+shell prompt now has `(hg-dev)` prepended to it? That's there to remind you
+that you're working in that environment.
+
+Creating the environment automatically puts you into it for that shell
+session. To get into it in the future you'll use:
+
+    workon hg-dev
+
+Now you need to link the Mercurial libraries you're going to change to this
+environment, so you can use it to test your code. Run the following three
+commands:
+
+    ln -s (full path to crew)/mercurial $WORKON_HOME/hg-dev/lib/python2.6/site-packages/
+    ln -s (full path to crew)/hgext $WORKON_HOME/hg-dev/lib/python2.6/site-packages/
+    ln -s (full path to crew)/hg $WORKON_HOME/hg-dev/bin/
+
+Replace `(full path to crew)` with the *full* path to your local crew
+repository, and `hg-dev` with the name of your virtual environment (if you
+named it differently than I did).
+
+Why Bother With a Virtual Environment?
+--------------------------------------
+
+It's probably the most work in this entire process, so why did I insist you
+set it up? Watch this:
+
+    :::console
+    sjl at ecgtheow in ~/src/hg-crew-sjl on default 
+    $ hg --version
+    Mercurial Distributed SCM (version 1.2.1)
+    
+    Copyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> and others
+    This is free software; see the source for copying conditions. There is NO
+    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    
+    sjl at ecgtheow in ~/src/hg-crew-sjl on default 
+    $ workon hg-dev
+    
+    (hg-dev)
+    sjl at ecgtheow in ~/src/hg-crew-sjl on default 
+    $ hg --version
+    Mercurial Distributed SCM (version 7956a823daa3)
+    
+    Copyright (C) 2005-2009 Matt Mackall <mpm@selenic.com> and others
+    This is free software; see the source for copying conditions. There is NO
+    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+    
+    (hg-dev)
+    sjl at ecgtheow in ~/src/hg-crew-sjl on default 
+    $ 
+
+Look at the version numbers. Notice how they changed?
+
+**You can now use** `workon hg-dev` **to make the** `hg` **command run
+Mercurial with your changes!**
+
+This makes it simple to test your work as you go. I keep two terminal windows
+open while working on the Mercurial source:
+
+* One is in my local crew repository to diff, commit, etc with the standard version of Mercurial.
+* The other is in a test repository.  I've run `workon hg-dev` to switch to my modified version so I can try out my changes.
+
+Get To Work!
+------------
+
+That's it for the initial setup. Now you can start adding all the wonderful
+features you have in mind. A simple workflow might go something like this:
+
+1. Open two terminal windows and use `workon hg-dev` in the second one to switch to the virtual environment.
+2. Make some changes to the Mercurial codebase.
+3. Test your changes in the second terminal window.
+4. Repeat 3 and 4, using the first terminal window to commit to the local repository as you go.
+
+Once you're finished with your shiny new feature, how do you get it into the
+main Mercurial code so we can all benefit from it?
+
+Modify the Test Suite
+---------------------
+
+Before you go off and submit a patch, you need to make sure it works with the
+current tests. You can run the tests by going to the repository and using:
+
+    cd tests
+    python run-tests.py
+
+It's going to take a while, just like before. If you changed something that
+modifies the output of a command it will probably break some of the existing
+tests. That's alright, but you'll need to fix them to reflect your changes.
+The simplest way to do this is to use the `--interactive` flag:
+
+    python run-tests.py --interactive
+
+Using `--interactive` will prompt you each time a test fails and ask if you
+want to accept the new output as the "correct" output. This makes it simple to
+update the existing tests to take your changes into account.
+
+Obviously you should **only accept these updates if they make sense**. Pay
+attention to the output and make sure you didn't accidentally break something!
+
+Add to the Test Suite
+----------------------
+
+If you've implemented an entirely new feature (as opposed to just modifying an
+existing one) you should add some tests of your own. This will make sure no
+one else will inadvertently break whatever you've added.
+
+There's a nice [guide][test-guide] to this on the Mercurial site. Follow it to
+add some tests for your changes.
+
+From what I've heard it's preferable to append to an existing set of tests (if
+it makes sense) instead of adding a brand new test file -- the tests run
+pretty slowly and adding new files make them even slower.
+
+[test-guide]: http://www.selenic.com/mercurial/wiki/WritingTests#Writing_a_shell_script_test
+
+Email Your Patches to the Mailing List
+--------------------------------------
+
+You've finally got your code working and updated the tests. It's time to share
+your changes with the rest of the Mercurial developers.
+
+If you want your patches to get accepted, you should take the time to read the
+[guide to contributing changes][] and the [guide to making successful
+patches][] on the Mercurial site. They're short but contain most of what you
+need to know.
+
+[guide to contributing changes]: http://www.selenic.com/mercurial/wiki/ContributingChanges
+[guide to making successful patches]: http://www.selenic.com/mercurial/wiki/SuccessfulPatch
+
+I prefer to use the [patchbomb][] extension to email the patches because it
+takes care of the formatting for me. To enable and configure it you'll need to
+make some additions to your `~/.hgrc` file:
+
+    :::text [extensions] hgext.patchbomb =
+    
+     [email] method = smtp from = Your Name <you@yourdomain.com>
+    
+     [smtp] host = smtp.youremailhost.com username = yourusername tls = True
+    
+    You'll need to tweak those settings with your own email address, mail
+    server, and so on. Once that's done, you can have patchbomb package up
+    your changes and email them out:
+
+    hg email --rev (your first revision):(your last revision)
+
+The command will guide you through filling out some more information, and then
+send out the patches. `hg help email` has a lot more information on how to use
+it.
+
+I usually email them to myself first just in case I mess up a revision number
+and email six thousand changesets. Flooding my own inbox is much better than
+flooding the list's.
+
+[patchbomb]: http://www.selenic.com/mercurial/wiki/PatchbombExtension
+
+That's It, Now Go Contribute!
+-----------------------------
+
+That's about the extent of my knowledge on contributing to Mercurial. As I
+said before, I've only done one patch so far, but I wanted to write this while
+everything about setting up the environment was fresh in my mind.
+
+If any of the other Mercurial developers would like to chime in and suggest
+corrections or additions -- or if anyone has any questions -- I'll be happy to
+update the post. I hope it's helpful!
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/08/a-guide-to-branching-in-mercurial.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,395 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "A Guide to Branching in Mercurial"
+    snip: "With illustrations and comparisons to git."
+    created: 2009-08-30 20:27:12
+%}
+
+{% block article %}
+
+<div class="no-img-borders">
+
+I've been hanging out in the [#mercurial][hg-irc] and [#bitbucket][bb-irc]
+channels on freenode a lot lately, and I've noticed a topic that comes up a
+lot is "how does [Mercurial][hg]'s branching differ from [git][]'s branching?"
+
+[hg]: http://mercurial.selenic.com/
+[git]: http://git-scm.com/
+[hg-irc]: irc://irc.freenode.net/#mercurial
+[bb-irc]: irc://irc.freenode.net/#bitbucket
+[freenode]: http://freenode.net/
+
+A while ago [Nick Quaranto][nick] and I were talking about Mercurial and git's
+branching models on Twitter and I wrote out a [quick longreply][lreply] about
+the main differences. Since then I've pointed some git users toward that post
+and they seemed to like it, so I figured I'd turn it into something a bit more
+detailed.
+
+**Disclaimer:** this post is not intended to be a guide to the commands used
+for working with Mercurial. It is only meant to be a guide to the *concepts*
+behind the branching models. For more information on daily use and commands,
+the [hg book][book] is a great resource (if you find it useful, please
+[buy][book-buy] a paper copy to support Bryan and have a printed copy of the
+[best editing fail of all time][editfail]).
+
+[nick]: http://litanyagainstfear.com/
+[lreply]: http://a.longreply.com/178502
+[book]: http://hgbook.red-bean.com/
+[book-buy]: http://search.barnesandnoble.com/Mercurial/Bryan-OSullivan/e/9780596800673/?itm=1
+[editfail]: http://twitpic.com/cwod4
+
+[TOC]
+
+Prologue
+--------
+
+Before I start explaining the different branching models, here's a simple
+repository I'll use as an example:
+
+![Basic Repository Diagram](/site-media/storage/blog/2009-08-30-branching/branch-base.png "Basic Repository")
+
+The repository is in the `~/src/test-project` folder. It has three changesets
+in it: numbers 0, 1 and 2.
+
+**For git users:** each changeset in a Mercurial repository has a hash as an
+identifier, just like with git. However, Mercurial also assigns numbers to
+each changeset in a repository. The numbers are *only* for that local
+repository -- two clones might have different numbers assigned to different
+changesets depending on the order of pulls/pushes/etc. They're just there for
+convenience while you're working with a repository.
+
+The default branch name in Mercurial is "default". Don't worry about what that
+means for now, we'll get to it. I'm mentioning it because there's a little
+`default` marker in the diagram.
+
+In all of these diagrams, a marker like that with a dashed border doesn't
+actually exist as an object anywhere. Those are special names that you can use
+to identify a changeset instead of the hash or number -- Mercurial will
+calculate the revision on the fly.
+
+For now, ignore the `default` marker. I've colored it grey in each of the
+diagrams where it doesn't matter.
+
+Branching with Clones
+---------------------
+
+The slowest, safest way to create a branch with Mercurial is to make a new
+clone of the repository:
+
+    $ cd ~/src
+    $ hg clone test-project test-project-feature-branch 
+
+Now you've got two copies of the repository. You can commit separately in each
+one and push/pull changesets between them as often as you like. Once you've
+made some changes in each one, the result might look like this:
+
+![Clone Diagram](/site-media/storage/blog/2009-08-30-branching/branch-clone.png "Branching with Clones")
+
+We've got two copies of the repository. Both contain the changesets that
+existed at the time we branched/cloned. If we push from `test-project` into
+`test-project-feature-branch` the "Fix a critical bug" changeset will be
+pushed over.
+
+**For git users:** Remember how I mentioned that the changeset numbers are
+local to a repository? We can see this clearly here -- there are two different
+changesets with the number 3. The numbers are *only* used while working inside
+a single repository. For pushing, pulling, or talking to other people you
+should use the hashes.
+
+### Advantages
+
+Cloning is a very safe way of creating a branch. The two repositories are
+completely isolated until you push or pull, so there's no danger of breaking
+anything in one branch when you're working in another.
+
+Discarding a branch you don't want any more is *very* easy with cloned
+branches. It's as simple as `rm -rf test-project-feature-branch`. There's no
+need to mess around with editing repository history, you just delete the damn
+thing.
+
+### Disadvantages
+
+Creating a branch by cloning locally is slower than the other methods, though
+Mercurial will use hardlinks when cloning if your OS supports them (most do)
+so it won't be *too* slow.
+
+However, the clone branching method can really slow things down when other
+developers (not located nearby) want to work on the project. If you publish
+two branches as separate repositories (such as `stable` and `version-2`),
+contributors will have to clone down *both* repositories through the internet
+if they want to work on both branches. That can take a lot of extra time,
+depending on the repository size and bandwidth.
+
+It can become especially wasteful if, for example, there are 10,000 changesets
+before the branch point and maybe 100 per branch after. Instead of pulling
+down 10,200 changesets you need to pull down 20,200. If you want to work on
+three different branches, you're pulling down 30,300 instead of 10,300.
+
+There is a way to avoid this large download cost, as pointed out by Guido
+Ostkamp and timeless_mbp in [#mercurial][hg-irc]. The idea is that you clone
+one branch down from the server, then pull *all* the branches into it, then
+clone locally to split that repository back into branches. This avoids the
+cost of cloning down the same changesets over and over.
+
+An example of this method with three branches would look something like this:
+
+    $ hg clone http://server/project-main project
+    $ cd project
+    $ hg pull http://server/project-branch1
+    $ hg pull http://server/project-branch2
+    $ cd ..
+    $ hg clone project project-main --rev [head of mainline branch]
+    $ hg clone project project-branch1 --rev [head of branch1]
+    $ hg clone project project-branch2 --rev [head of branch2]
+    $ rm -rf project
+    $ cd project-main
+    $ [edit .hg/hgrc file to make the default path http://server/project-main]
+    $ cd ../project-branch1
+    $ [edit .hg/hgrc to make the default path http://server/project-branch1]
+    $ cd ../project-branch2
+    $ [edit .hg/hgrc to make the default path http://server/project-branch2]
+
+This example assumes you know the IDs of the branch heads off the top of your
+head, which you probably don't. You'll have to look them up.
+
+It also assumes that there is only one new head per branch, when there might
+be more. If `branch1` has two heads which are not in `mainline`, you would
+need to look up the IDs of *both* and specify both in the clone command.
+
+Another annoyance shows up when you're working on a project that relies on
+your code being at a specific file path. If you branch by cloning you'll need
+to rename directories (or change the file path configuration) every time you
+want to switch branches. This might not be a common situation (most build
+tools don't care about the absolute path to the code) but it *does* appear now
+and then.
+
+I personally don't like this method and don't use it. Others do though, so
+it's good to understand it (Mercurial itself uses this model).
+
+### Comparison to git
+
+Git can use this method of branching too, although I don't see it very often.
+Technically this is the exact same thing as creating a fork on [GitHub][], but
+most people think of "fork" and "branch" as separate concepts.
+
+[GitHub]: http://github.com/
+
+Branching with Bookmarks
+------------------------
+
+The next way to branch is to use a bookmark.  For example:
+
+    $ cd ~/src/test-project
+    $ hg bookmark main
+    $ hg bookmark feature
+
+[bookmark]: http://mercurial.selenic.com/wiki/BookmarksExtension
+
+Now you've got two bookmarks (essentially a tag) for your two branches at the
+current changeset.
+
+To switch to one of these branches you can use `hg update feature` to update
+to the tip changeset of that branch and mark yourself as working on that
+branch. When you commit, it will move the bookmark to the newly created
+changeset.
+
+**Note:** for more detailed information on actually using bookmarks day-to-day please read the [bookmarks page][bookmark].  This guide is meant to show the different branching models, and bookmarks have a few quirks that you should know about if you're going to use them.
+
+Here's what the repository would look like with this method:
+
+![Bookmark Diagram](/site-media/storage/blog/2009-08-30-branching/branch-bookmark.png "Branching with Bookmarks")
+
+The diagram of the changesets is pretty simple: the branch point was at
+changeset 2 and each branch has one new changeset on it.
+
+Now let's look at the markers. The `default` marker is still there, and we're
+still going to ignore it.
+
+There are two new labels in this diagram -- these represent the bookmarks.
+Notice how their outlines are *not* dashed? This is because bookmarks are
+actual objects stored on disk, not just convenient shortcuts that Mercurial
+will let you use.
+
+When you use a bookmark name as a revision Mercurial will look up the revision
+it points at and use that.
+
+### Advantages
+
+Bookmarks give you a quick, lightweight way to give meaningful label your
+branches.
+
+You can delete them when you no longer need them. For example, if we finish
+development of the new feature and merge the changes in the main branch, we
+probably don't need to keep the `feature` bookmark around any more.
+
+### Disadvantages
+
+Being lightweight can also be a disadvantage. If you delete a bookmark, then
+look at your code a year later and wonder what all those changesets that got
+merged into main were for, the bookmark name is gone. This probably isn't a
+big issue if you write good changeset summaries.
+
+Bookmarks are local. They do *not* get transferred during a push or pull!
+There has been some whispering about adding this is Mercurial 1.4, but for now
+if you want to give someone else your bookmarks you'll need to manually give
+them the file the bookmarks are kept in.
+
+### Comparison to git
+
+Branching with bookmarks is very close to the way git usually handles
+branching. Mercurial bookmarks are like git refs: named pointers to changesets
+that move on commit.
+
+The biggest difference is that git refs are transferred when pushing/pulling
+and Mercurial bookmarks are not.
+
+Branching with Named Branches
+-----------------------------
+
+The third way of branching is to use Mercurial's named branches. Some people
+prefer this method (myself included) and many others don't.
+
+To create a new named branch:
+
+    $ cd ~/src/test-project
+    $ hg branch feature
+
+When you commit the newly created changeset will be on the same branch as its
+parent, unless you've used `hg branch` to mark it as being on a different one.
+
+Here's what a repository using named branches might look like:
+
+![Named Branch Diagram](/site-media/storage/blog/2009-08-30-branching/branch-named.png "Branching with Named Branches")
+
+An important difference with this method is that the branch name is
+permanently recorded as part of the changeset's metadata (as you can see in
+changeset 4 in the diagram).
+
+**Note:** The default branch is called `default` and is not normally shown
+unless you ask for verbose output.
+
+Now it's time to explain those magic dashed-border labels we've been ignoring.
+Using a branch name to specify a revision is shorthand for "the tip changeset
+of this named branch". In this example repository:
+
+* Running `hg update default` would update to changeset 3, which is the tip of the `default` branch.
+* Running `hg update feature` would update to changeset 4, which is the tip of the `feature` branch.
+
+Neither of these labels actually exist as an object anywhere on disk (like a
+bookmark would). When you use them Mercurial calculates the appropriate
+revision on the fly.
+
+### Advantages
+
+The biggest advantage to using named branches is that every changeset on a
+branch has the branch name as part of its metadata, which I find very helpful
+(especially when using [graphlog][]).
+
+[graphlog]: http://mercurial.selenic.com/wiki/GraphlogExtension
+
+### Disadvantages
+
+Many people don't like cluttering up changeset metadata with branch names,
+especially if they're small branches that are going to be merged pretty
+quickly.
+
+In the past there was also the problem of not having a way to "close" a
+branch, which means that over time the list of branches could get huge. This
+was fixed in Mercurial 1.2 which introduced the `--close-branch` option for
+`hg commit`.
+
+### Comparison to git
+
+As far as I know git has no equivalent to Mercurial's named branches. Branch
+information is never stored as part of a git changeset's metadata.
+
+Branching Anonymously
+---------------------
+
+The last method of branching with Mercurial is the fastest and easiest: update
+to any revision you want and commit. You don't have to think up a name for it
+or do anything else -- just update and commit.
+
+When you update to a specific revision, Mercurial will mark the parent of the
+working directory as that changeset. When you commit, the newly created
+changeset's parent will be the parent of the working directory.
+
+The result of updating and committing without doing anything else would be:
+
+![Anonymous Diagram](/site-media/storage/blog/2009-08-30-branching/branch-anon.png "Branching Anonymously")
+
+How do you switch back and forth between branches once you do this? Just use
+`hg update --check REV` with the revision number (or hash) (you can shorten
+`--check` to `-c`).
+
+**Note:** the `--check` option was added in Mercurial 1.3, but it was broken.
+It's fixed in 1.3.1. If you're using something earlier than 1.3.1, you really
+should update.
+
+Logging commands like `hg log` and `hg graphlog` will show you all the
+changesets in the repository, so there's no danger of "losing" changesets.
+
+### Advantages
+
+This is the fastest, easiest way to branch. You don't have to think of a name
+or close/delete anything when you're finished -- just update and commit.
+
+This method is *great* for quick-fix, two-or-three-changeset branches.
+
+### Disadvantages
+
+Using anonymous branching obviously means that there won't be any descriptive
+name for a branch, so you'll need to write good commit messages if you want to
+remember what a branch was for a couple of months later.
+
+Not having a single name to represent a branch means that you'll need to look
+up the revision numbers or hashes with `hg log` or `hg graphlog` each time you
+want to switch back and forth. If you're switching a lot this might be more
+trouble than it's worth.
+
+### Comparison to git
+
+Git has no real way to handle this. Sure, it lets you update and commit, but
+if you don't create a (named) ref to that new commit you're never going to
+find it again once you switch to another one. Well, unless you feel like
+grep'ing through a bunch of log output.
+
+Oh, and hopefully it doesn't get garbage collected.
+
+Sometimes you might not want to think up a name for a quick-fix branch. With
+git you *have* to name it if you want to really do anything with it, with
+Mercurial you don't.
+
+One More Difference Between Mercurial and git
+---------------------------------------------
+
+There's one more *big* difference between Mercurial's branching and git's
+branching:
+
+**Mercurial will push/pull *all* branches by default, while git will push/pull only the *current* branch.**
+
+This is important if you're a git user working with Mercurial. If you want to
+push/pull only a single branch with Mercurial you can use the `--rev` option
+(`-r` for short) and specify the tip revision of the branch:
+
+    $ hg push --rev branchname
+    $ hg push --rev bookmarkname
+    $ hg push --rev 4
+
+If you specify a revision, Mercurial will push that changeset and any
+ancestors of it that the target doesn't already have.
+
+This doesn't apply when you use the "Branching with Clones" method because the
+branches are separate repositories.
+
+Conclusion
+----------
+
+I hope this guide is helpful. If you see anything I've missed, especially on
+the git side of things (I don't use git any more than I have to) or have any
+questions please let me know!
+
+</div>
+
+{% endblock %}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/content/blog/2009/11/my-sitesprint-project-lindyhub.html	Wed Dec 23 20:24:31 2009 -0500
@@ -0,0 +1,196 @@
+{% extends "_post.html" %}
+
+{% hyde
+    title: "My SiteSprint Project: LindyHub"
+    snip: "I want to make something awesome for dancers."
+    created: 2009-11-16 19:15:07
+%}
+
+{% block article %}
+
+If you're a web designer and/or developer, you might have heard of
+[SiteSprint][]. From the SiteSprint page:
+
+>What is the Site Sprint?  
+>A challenge to do something about our personal websites. If you were looking 
+>for a reason to rework an existing site or launch a new one, here it is.
+
+The event has a couple of rules:
+
+>The Rules  
+>1. Launch by 12/15  
+>2. Document your process  
+>3. On launch, share what you did and how you did it
+
+I've decided to join in and finish up a pet project of mine that I've been
+working on (very sporadically) for the past six months or so: [LindyHub][]
+
+[SiteSprint]: http://sitesprint.info/
+[LindyHub]: http://lindyhub.com/
+
+[TOC]
+
+Preface: About Swing Dancing
+----------------------------
+
+If you're a dancer, go ahead and skip to the next section. This is for the
+programmers and designers that might not have heard of Lindy Hop.
+
+[Lindy Hop][] is a form of swing dancing. I've been doing it for six years and
+love it.
+
+Part of the Lindy Hop culture consists of "exchanges" and "workshop weekends".
+The general idea is that a group of dancers will host one of these events on a
+weekend. They'll hire DJs or bands, and teachers if they're going to have
+classes, and plan out a whole weekend of awesomeness.
+
+Dancers from far and wide will travel to these events to meet and dance with
+new people (and old friends).
+
+If you want more background on dancing post a comment and I'll gladly explain
+more, but this in-a-nutshell explanation should be enough for you to
+understand the rest of this entry.
+
+[Lindy Hop]: http://en.wikipedia.org/wiki/Lindy_hop
+
+The Problem
+-----------
+
+LindyHub is a project I've been working on for about six months off and on in
+my spare time and it was rolling around in my head before that.
+
+Over the last few years or so I've been getting back into web development and
+design. At the beginning of this year I started to notice a trend: most
+websites for Lindy Hop and blues events are very basic and unpolished. Some of
+the things I've noticed about almost every event site:
+
+* They have a form for you to register for the event, but the form almost never has any nice inline validation of your input.
+* Every site's form is different -- you have to read every single one carefully to see exactly what they want.
+* You end up entering the same information every single time for every event: name, phone number, email, etc.
+* Housing is a toss up.  Sometimes they have a place for it in the registration form, other times they just say "Email aaa@bbb.com if you need housing."  That's a lot of emails for the housing coordinator to sort through and quite often it can become a mess.
+* Some of them list addresses for each venue, which is great for those of us that have GPSes.  Sometimes they just give driving directions to and from each one, which is terrible if you just want to type each one into your GPS or print off directions from Google Maps before you go.
+* Only one event that I've gone to ([Blues Muse][] in Philly) has had a "Who's Coming" list so you could see who else was going to the event (you could choose whether or not to let them show your name when you registered). Sometimes you can figure this out from Facebook event pages, but that's pretty unreliable.
+
+There are other things, but those are the big ones.
+
+Now, I completely understand why people don't add those features to their
+event sites. It doesn't make sense to spend 10 hours adding cool features that
+are nice to have but not really necessary if your website is only going to be
+used for a single event. Those 10 hours could be spent promoting your event
+and getting more people to come which is better for everyone.
+
+Around the time I was noticing these things I was also starting to get back
+into contributing to open source projects. Two of the big project hosting
+sites nowadays are [BitBucket][] and [GitHub][]. I noticed how they both make
+starting a new project almost trivially easy -- you sign up for an account and
+within two minutes people can view and contribute back to your new project.
+They've fostered a lot of collaboration in the open source community and it's
+been a very good thing all around.
+
+The two ideas came together in my head pretty quickly. I started thinking
+about designing a site that made setting up a dance event almost as easy as
+forking a project on BitBucket.
+
+Sure, every organizer spending 10 hours to add cool features to their event
+site doesn't really make sense. But what if one person spent a couple hundred
+hours and built a site that let every organizer add those features in 10
+*minutes*? After 20 or 30 events it's saved those couple hundred hours and
+just gets better from there.
+
+The more I thought about it the more it seemed like a good idea. I'd been
+learning a lot about web development and about six months ago I decided I was
+competent enough to handle something like this, and started working on the
+LindyHub core.
+
+[Blues Muse]: http://www.lindyandblues.com/events/2009/bluesmuse/
+[BitBucket]: http://bitbucket.org/
+[GitHub]: http://github.com/
+
+LindyHub's Current State
+------------------------
+
+I've been working on LindyHub off and on for the past six months or so, and it
+has been coming along pretty well. I decided to use SiteSprint as motivation
+to buckle down and complete it to a point where I can invite a few organizers
+to give it a try in a "closed-beta" period. From there I'll work out any kinks
+and open it up for public use.
+
+Here are some of the things the site can do *right now*:
+
+* Users can sign up and create profiles for themselves.  "Forgot my password" and such is supported.
+* They can view (and search for) events that are happening in the future, and comment on them.
+* They can create a new event and add things to its schedule.
+* The schedule is formatted nicely.  If an event starts before 5 AM it's grouped with the previous day's events because it's probably a late night dance.
+* Venues will add links to Google Maps if the organizers put in the address.
+* Organizers can let LindyHub handle event registration for them.  They specify how they want to be paid: door, check, and/or PayPal.  If it's PayPal, LindyHub takes the email address that should receive the money and handles creating the PayPal "Buy Now" button.
+* Early registration is supported -- organizers can specify a cutoff date and the early/late prices if they like.
+* LindyHub doesn't *have* to be used for the registration.  Organizers can opt to handle registration themselves and just put the event on LindyHub to help more people find it.
+* Users can register for events quickly and easily.  LindyHub will ask them how they want to pay and tell them how to do it.
+* When they register they can allow other people to see that they're going to the event.  If they do, they'll show up in the list on the event page.
+* Organizers can see nicely formatted lists of registration/payment information and housing requests.
+
+My Goals for the Sprint (and Beyond)
+------------------------------------
+
+Some of the things I'm planning on adding to the site in during the sprint
+are:
+
+* Redesign the interface.  I'm not a designer, but I can certainly do better than the spartan design I've thrown together during development.
+* Better, Javascript-based form fields.  They'll validate the input before you even click "Submit" (so you can correct mistakes immediately) and provide nice date/time pickers for the date and time fields.  I wanted to make sure the site works 100% for people with JavaScript turned off before I started relying on it to make things pretty.
+* Mobile stylesheets for iPhone users.
+* Tagging events with tags like "lindyhop, blues, workshop, exchange, gordonwebster, etc."  This will make it easier to find events you're interested in.  This will also be easy to add.
+* "Friending" other users.  This would let you see what your friends are going to and would be awesome (for me, at least).
+* Location-based features.  LindyHub can already store your hometown and the locations of events.  It wouldn't be terribly difficult to parse this information into a latitude and longitude.  Once that's done it's simple to calculate the distance to events and say "Show me all events within 300 miles of my hometown" or "Show me everyone going to this event that lives within 30 miles of me because we might want to carpool."
+* Automatically email reminders to people a week before the event.  The emails could include links to Google Maps for the first (and other) venues to make it take only one click to print directions.  There are a lot of other things that would be nice to include too -- I've been holding off on this because it really requires the attention of a copywriter to get right.
+* Provide an easy-to-use interface for organizers to assign people that have requested housing to people that offer it.
+* Send emails to guest/host groups automatically to make sure guests have their host's contact information (and vice versa).
+* Translations into different languages.  This will be pretty simple if someone wants to volunteer to translate (I only speak English and American Sign Language myself).
+* Suggesting events a user might like.  This is something for the far future, but it would give me a chance to play around in another favorite area of mine: artificial intelligence.  I have some ideas on how to implement it but it's not critical so I'm not looking at it right now.
+
+There are a whole slew of other things I have tumbling about in my head, but
+those should be enough to give you an idea of where the site can go.
+
+**Above all, my goal is to spend as much time as it takes to create a site
+that will save organizers a few hours of their time and make it easier for
+dancers to find events they want to go to.**
+
+I *don't* want to try to create a site that will accommodate *every* event. If
+I make LindyHub flexible enough to handle Frankie 95 it will become so
+complicated that no other events will want to use it. I want it to work for
+the 85% or 90% of events that just need the most common features. Doing that
+will make it far, far easier to use, which means more people will use it.
+
+For the Nerds: What I'm Using
+-----------------------------
+
+LindyHub is built with [Django][] and [Python][].
+
+It's hosted on [WebFaction][] and uses a [PostgreSQL][] database to store its
+data.
+
+It uses [Aardvark Legs][] to keep me sane while writing the CSS, and will use
+[jQuery][] for the inline form validation.
+
+I'm happy to go further in depth if you're curious -- let me know with a
+comment.
+
+[Django]: http://www.djangoproject.com/
+[Python]: http://python.org/
+[WebFaction]: http://www.webfaction.com/?affiliate=sjl
+[PostgreSQL]: http://www.postgresql.org/
+[Aardvark Legs]: http://fecklessmind.com/2009/01/20/aardvark-css-framework/
+[jQuery]: http://jquery.com/
+
+If You're Interested, Follow My Progress!
+-----------------------------------------
+
+I'm going to be working on the site a lot over the next month. I might write
+another blog entry or two, but I'll try to post updates to
+[@lindyhub][twitter] on Twitter much more often.
+
+If there's anything specific you want to know post a comment here and I'll be
+happy to answer!
+
+[twitter]: http://twitter.com/lindyhub/
+
+{% endblock %}
\ No newline at end of file
--- a/layout/_post.html	Wed Dec 23 19:37:10 2009 -0500
+++ b/layout/_post.html	Wed Dec 23 20:24:31 2009 -0500
@@ -1,13 +1,13 @@
 {% extends "skeleton/_base.html" %}
 
 {% block content %}
-    <div id="leaf-title"><h1>{{ page.title }}</h1></div>
+    <div id="leaf-title"><h1>{{ page.title|safe }}</h1></div>
     
     <div id="leaf-content">
         {% filter typogrify %}
             {% article %}
                 {% markdown %}
-                        {% block article %}{% endblock %}
+                    {% block article %}{% endblock %}
                 {% endmarkdown %}
             {% endarticle %}
         {% endfilter %}
--- a/layout/skeleton/_base.html	Wed Dec 23 19:37:10 2009 -0500
+++ b/layout/skeleton/_base.html	Wed Dec 23 20:24:31 2009 -0500
@@ -36,7 +36,7 @@
         <div id="main-wrap">
             <div id="header">
                 <h1>
-                    <a href="/">steve losh</a> <span class="page-title">/ {{ page.title }}</span>
+                    <a href="/">steve losh</a> <span class="page-title">/ {{ page.title|safe }}</span>
                 </h1>
             </div>
             
--- a/layout/skeleton/_innerlisting.html	Wed Dec 23 19:37:10 2009 -0500
+++ b/layout/skeleton/_innerlisting.html	Wed Dec 23 20:24:31 2009 -0500
@@ -9,10 +9,10 @@
             <li>
                 <a href="{{ list_page.url }}">
                     {% with list_page.name_without_extension|remove_date_prefix|unslugify as default_title %}
-                        {{ list_page.title|default_if_none:default_title }}
+                        {{ list_page.title|default_if_none:default_title|safe }}
                     {%endwith%}
                 </a>
-                <span class="snip">{{ list_page.snip }}</span>
+                <span class="snip">{{ list_page.snip|safe }}</span>
             </li>
         {%endif%}
     {% endifnotequal %}
--- a/media/css/base.css	Wed Dec 23 19:37:10 2009 -0500
+++ b/media/css/base.css	Wed Dec 23 20:24:31 2009 -0500
@@ -87,6 +87,7 @@
 
 #content {
 	width: 42em;
+	margin-bottom: 5em;
 }
 
 div#section-listing {