<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="text">Free PeepCode Blog</title>
  <generator uri="http://effectif.com/nesta">Nesta</generator>
  <id>tag:blog.peepcode.com,2009:/</id>
  <link href="http://blog.peepcode.com/articles.xml" rel="self"/>
  <link href="http://blog.peepcode.com" rel="alternate"/>
  <subtitle type="text">Short, Free Screencasts for Web Developers and Alpha Geeks</subtitle>
  <entry>
    <title>Geek Crushes</title>
    <link href="http://blog.peepcode.com/blog/2012/geek-crushes" type="text/html" rel="alternate"/>
    <id>tag:blog.peepcode.com,2012-02-14:/blog/2012/geek-crushes</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;This article is heavily styled and is best viewed at &lt;a href="http://blog.peepcode.com/blog/2012/geek-crushes"&gt;PeepCode&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;div id='geek-crushes'&gt;
  &lt;div class='row valentine'&gt;
    &lt;img class='stamp' src='geek-crushes/img/stamps/plane-stripes.png' /&gt;
    &lt;div class='column letter'&gt;
      &lt;h2 class='alignleft'&gt;
        Dear
        &lt;span class='name'&gt;
          Christian Neukirchen,
        &lt;/span&gt;
      &lt;/h2&gt;
      &lt;p&gt;The first time I saw you, I was too shy to talk to you. Then you taught me how to use &lt;code&gt;zsh&lt;/code&gt;. Now I use it every day.&lt;/p&gt;
      &lt;p&gt;One would think that the author of products used by millions of people would get some respect (the &lt;a href="http://chneukirchen.org/trivium/"&gt;tumblelog&lt;/a&gt; and &lt;a href="http://rack.rubyforge.org/"&gt;Rack&lt;/a&gt;). But most developers don&amp;#8217;t even know your name, much less pronounce it correctly.&lt;/p&gt;
      &lt;p&gt;You promote your open source software as loudly as a ninja traverses a busy street. You launch your ideas silently and wait a few years for people to realize their brilliance.&lt;/p&gt;
      &lt;p&gt;I think about you every time I type &lt;code&gt;rackup config.ru&lt;/code&gt;.&lt;/p&gt;
      &lt;h2 class='alignright'&gt;
        Geekily Yours,
        &lt;br /&gt;
        &lt;span class='name'&gt;
          Geoffrey Grosenbach
        &lt;/span&gt;
      &lt;/h2&gt;
    &lt;/div&gt;
    &lt;div class='column address'&gt;
      &lt;h2&gt;
        Send To:
      &lt;/h2&gt;
      &lt;div class='polaroid'&gt;
        &lt;a href='https://github.com/chneukirchen'&gt;
          &lt;img src='geek-crushes/img/people/christian-neukirchen-2.jpg' /&gt;
        &lt;/a&gt;
        &lt;p&gt;
          &lt;img src='geek-crushes/img/link.png' /&gt;
          &lt;a href='https://github.com/chneukirchen'&gt;
            &lt;img src='geek-crushes/img/chneukirchen.png' /&gt;
          &lt;/a&gt;
        &lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row wrapper'&gt;
    &lt;div class='row valentine'&gt;
      &lt;img class='stamp' src='geek-crushes/img/stamps/plane-stripes.png' /&gt;
      &lt;div class='column letter'&gt;
        &lt;h2 class='alignleft'&gt;
          Dear
          &lt;span class='name'&gt;
            Jeremy Ashkenas,
          &lt;/span&gt;
        &lt;/h2&gt;
        &lt;p&gt;An athlete with as many successes as you&amp;#8217;ve had would be checked for performance enhancing drugs.&lt;/p&gt;
        &lt;p&gt;&lt;a href="http://documentcloud.github.com/backbone/"&gt;Backbone.js&lt;/a&gt;, &lt;a href="http://coffeescript.org/"&gt;CoffeeScript&lt;/a&gt;, Jammit, Docco, The Shoebox. The list goes on.&lt;/p&gt;
        &lt;p&gt;You&amp;#8217;re doing real work that&amp;#8217;s changing the world.&lt;/p&gt;
        &lt;p&gt;Keep on.&lt;/p&gt;
        &lt;h2 class='alignright'&gt;
          Indenting daily,
          &lt;br /&gt;
          &lt;span class='name'&gt;
            Geoffrey Grosenbach
          &lt;/span&gt;
        &lt;/h2&gt;
      &lt;/div&gt;
      &lt;div class='column address'&gt;
        &lt;h2&gt;
          Send To:
        &lt;/h2&gt;
        &lt;div class='polaroid'&gt;
          &lt;a href='https://github.com/jashkenas'&gt;
            &lt;img src='geek-crushes/img/people/jeremy-ashkenas-1.jpg' /&gt;
          &lt;/a&gt;
          &lt;p&gt;
            &lt;img src='geek-crushes/img/link.png' /&gt;
            &lt;a href='https://github.com/jashkenas'&gt;
              &lt;img src='geek-crushes/img/jashkenas.png' /&gt;
            &lt;/a&gt;
          &lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row valentine'&gt;
    &lt;img class='stamp' src='geek-crushes/img/stamps/plane-stripes.png' /&gt;
    &lt;div class='column letter'&gt;
      &lt;h2 class='alignleft'&gt;
        Dear
        &lt;span class='name'&gt;
          Reginald Braithwaite,
        &lt;/span&gt;
      &lt;/h2&gt;
      &lt;p&gt;I&amp;#8217;m glad you didn&amp;#8217;t get the notice that tech geeks don&amp;#8217;t &lt;a href="https://github.com/raganwald/homoiconic"&gt;blog&lt;/a&gt; anymore.&lt;/p&gt;
      &lt;p&gt;Half the stuff you talk about confuses me. What the hell is a K-combinator? I have no idea but now I&amp;#8217;m going to &lt;a href="http://leanpub.com/combinators"&gt;find out&lt;/a&gt;.&lt;/p&gt;
      &lt;p&gt;And then I find out that you do my &lt;a href="http://leanpub.com/shippingsoftware"&gt;favorite sport&lt;/a&gt;. Rock on.&lt;/p&gt;
      &lt;h2 class='alignright'&gt;
        XOXOX,
        &lt;br /&gt;
        &lt;span class='name'&gt;
          Geoffrey Grosenbach
        &lt;/span&gt;
      &lt;/h2&gt;
    &lt;/div&gt;
    &lt;div class='column address'&gt;
      &lt;h2&gt;
        Send To:
      &lt;/h2&gt;
      &lt;div class='polaroid'&gt;
        &lt;a href='https://github.com/raganwald'&gt;
          &lt;img src='geek-crushes/img/people/reginald-braithwaite-2.jpg' /&gt;
        &lt;/a&gt;
        &lt;p&gt;
          &lt;img src='geek-crushes/img/link.png' /&gt;
          &lt;a href='https://github.com/raganwald'&gt;
            &lt;img src='geek-crushes/img/raganwald.png' /&gt;
          &lt;/a&gt;
        &lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row wrapper'&gt;
    &lt;div class='row valentine'&gt;
      &lt;img class='stamp' src='geek-crushes/img/stamps/plane-stripes.png' /&gt;
      &lt;div class='column letter'&gt;
        &lt;h2 class='alignleft'&gt;
          Dear
          &lt;span class='name'&gt;
            Blake Mizerany,
          &lt;/span&gt;
        &lt;/h2&gt;
        &lt;p&gt;It takes a true visionary to make simple tools that can do everything.&lt;/p&gt;
        &lt;p&gt;Maybe even more impressive than the individual success of &lt;a href="http://www.sinatrarb.com/"&gt;Sinatra&lt;/a&gt; is that it&amp;#8217;s always the first to be implemented in every other language that sprouts up.&lt;/p&gt;
        &lt;p&gt;But that didn&amp;#8217;t stop you from building &lt;a href="https://github.com/ha/doozerd"&gt;other mind-bending tools&lt;/a&gt; that most other developers wouldn&amp;#8217;t even attempt. In a language you learned for the first time while writing it.&lt;/p&gt;
        &lt;h2 class='alignright'&gt;
          Here&#8217;s to you,
          &lt;br /&gt;
          &lt;span class='name'&gt;
            Geoffrey Grosenbach
          &lt;/span&gt;
        &lt;/h2&gt;
      &lt;/div&gt;
      &lt;div class='column address'&gt;
        &lt;h2&gt;
          Send To:
        &lt;/h2&gt;
        &lt;div class='polaroid'&gt;
          &lt;a href='https://github.com/bmizerany'&gt;
            &lt;img src='geek-crushes/img/people/blake-mizerany-1.jpg' /&gt;
          &lt;/a&gt;
          &lt;p&gt;
            &lt;img src='geek-crushes/img/link.png' /&gt;
            &lt;a href='https://github.com/bmizerany'&gt;
              &lt;img src='geek-crushes/img/bmizerany.png' /&gt;
            &lt;/a&gt;
          &lt;/p&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row valentine'&gt;
    &lt;img class='stamp' src='geek-crushes/img/stamps/plane-stripes.png' /&gt;
    &lt;div class='column letter'&gt;
      &lt;h2 class='alignleft'&gt;
        Dear
        &lt;span class='name'&gt;
          Elise Worthy,
        &lt;/span&gt;
      &lt;/h2&gt;
      &lt;p&gt;Most people would give up after trying to learn something for a few weeks. You&amp;#8217;ve kept on with programming for several years and are getting better at it all the time.&lt;/p&gt;
      &lt;p&gt;Yet you&amp;#8217;re an incredible &lt;a href="http://workshops.railsbridge.org/2011/10/seattle-railsbridge-growing-growing/"&gt;teacher&lt;/a&gt; too. And working with you has irrevocably changed the way I think about business.&lt;/p&gt;
      &lt;h2 class='alignright'&gt;
        Best of luck at Living Social,
        &lt;br /&gt;
        &lt;span class='name'&gt;
          Geoffrey Grosenbach
        &lt;/span&gt;
      &lt;/h2&gt;
    &lt;/div&gt;
    &lt;div class='column address'&gt;
      &lt;h2&gt;
        Send To:
      &lt;/h2&gt;
      &lt;div class='polaroid'&gt;
        &lt;a href='https://github.com/eliseworthy'&gt;
          &lt;img src='geek-crushes/img/people/elise-worthy-1.jpg' /&gt;
        &lt;/a&gt;
        &lt;p&gt;
          &lt;img src='geek-crushes/img/link.png' /&gt;
          &lt;a href='https://github.com/eliseworthy'&gt;
            &lt;img src='geek-crushes/img/eliseworthy.png' /&gt;
          &lt;/a&gt;
        &lt;/p&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</content>
    <published>Tue Feb 14 23:00:00 +0000 2012</published>
  </entry>
  <entry>
    <title>My Command Line Prompt</title>
    <link href="http://blog.peepcode.com/blog/2012/my-command-line-prompt" type="text/html" rel="alternate"/>
    <id>tag:blog.peepcode.com,2012-01-05:/blog/2012/my-command-line-prompt</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;This article is heavily styled and is best viewed at &lt;a href="http://blog.peepcode.com/blog/2012/my-command-line-prompt"&gt;PeepCode&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;div id='commandline'&gt;
  &lt;div class='row notations'&gt;
    &lt;div class='column'&gt;
      &lt;p id='by'&gt;
        by Geoffrey Grosenbach &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Paula Lavalle
      &lt;/p&gt;
      &lt;figure id='prompt'&gt;
        &lt;img alt='Command Line Prompt' height='325' src='my-command-line-prompt/img/prompt-with-arrows.png' width='940' /&gt;
        &lt;div class='notation' id='path'&gt;
          Current Path
          &lt;br /&gt;
          &lt;a href='#currentpath'&gt;More&lt;/a&gt;
        &lt;/div&gt;
        &lt;div class='notation' id='smiley'&gt;
          Last Command Status
          &lt;br /&gt;
          &lt;a href='#status'&gt;More&lt;/a&gt;
        &lt;/div&gt;
        &lt;div class='notation' id='scm-dirty'&gt;
          Uncommitted Git Changes
          &lt;br /&gt;
          &lt;a href='#gitbranch'&gt;More&lt;/a&gt;
        &lt;/div&gt;
        &lt;div class='notation' id='ruby'&gt;
          RVM Config
          &lt;br /&gt;
          &lt;a href='#rvmconfig'&gt;More&lt;/a&gt;
        &lt;/div&gt;
        &lt;div class='notation' id='git-status'&gt;
          Git Branch
          &lt;br /&gt;
          &lt;a href='#gitbranch'&gt;More&lt;/a&gt;
        &lt;/div&gt;
      &lt;/figure&gt;
      &lt;div id="buy"&gt;&lt;h2&gt;Advanced Git!&lt;/h2&gt;&lt;p class="small"&gt;One hour video.&lt;br /&gt;Only &lt;sup&gt;$&lt;/sup&gt;12!&amp;nbsp;&lt;a href="http://peepcode.com/products/advanced-git"&gt;More Info&amp;hellip;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div id='description'&gt;
  &lt;div class='row'&gt;
    &lt;div class='column'&gt;
      &lt;h2&gt;Your Command Line Dashboard&lt;/h2&gt;
      &lt;p&gt;In 10 years you&amp;#8217;ll probably be writing code in a different language, building web apps with a different framework, and wearing a different pair of underwear.&lt;/p&gt;
      &lt;p&gt;But the command line prompt you use today could still be serving you well.&lt;/p&gt;
      &lt;p&gt;Many of the elements of my command prompt were snitched from other developers (&lt;a href="https://github.com/chneukirchen"&gt;Christian Neukirchen&lt;/a&gt;, &lt;a href="https://github.com/freelancing-god"&gt;Pat Allan&lt;/a&gt;, and &lt;a href="https://github.com/benhoskings"&gt;Ben Hoskings&lt;/a&gt;). Here are my goals for my command prompt.&lt;/p&gt;
      &lt;h3&gt;Goals&lt;/h3&gt;
      &lt;ul&gt;
      	&lt;li&gt;&lt;strong&gt;Fast&lt;/strong&gt;: If I can tell there&amp;#8217;s a pause when I open a window or change directories, it&amp;#8217;s too slow.&lt;/li&gt;
      	&lt;li&gt;&lt;strong&gt;Terse&lt;/strong&gt;: Only show information that will change frequently between projects or between commands. If I always used the same version of Ruby, I would probably remove the Ruby version from my prompt.&lt;/li&gt;
      	&lt;li&gt;&lt;strong&gt;Mine&lt;/strong&gt;: I don&amp;#8217;t hesitate to customize a script that I copied from someone else. The prompt is not the place to worry about reusable or generalized code. It &lt;em&gt;should&lt;/em&gt; be easy to read and change when I need to.&lt;/li&gt;
      &lt;/ul&gt;
      &lt;h3&gt;Why &lt;span class="caps"&gt;ZSH&lt;/span&gt;?&lt;/h3&gt;
      &lt;p&gt;I switched to &lt;code&gt;zsh&lt;/code&gt; after receiving a one-on-one tutorial from &lt;a href="https://github.com/chneukirchen"&gt;Christian Neukirchen&lt;/a&gt;. It has some nice features:&lt;/p&gt;
      &lt;ul&gt;
      	&lt;li&gt;&lt;strong&gt;Separate prompt&lt;/strong&gt; for the right and left side of the screen.&lt;/li&gt;
      	&lt;li&gt;&lt;strong&gt;Inline completion&lt;/strong&gt; of directories, Git branch names, Rake task names, etc.&lt;/li&gt;
      	&lt;li&gt;&lt;strong&gt;Easy loop syntax&lt;/strong&gt;: &lt;code&gt;for f (`ls`) echo $f&lt;/code&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;Try the source to a &lt;a href="https://github.com/topfunky/zsh-simple"&gt;simple version of my prompt on GitHub&lt;/a&gt;. Or read the explanation below and build your own.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class='implement'&gt;
  &lt;div class='row'&gt;
    &lt;div class='column'&gt;
      &lt;h2&gt;
        Implementation
      &lt;/h2&gt;
      &lt;h3&gt;Setup&lt;/h3&gt;
      &lt;p&gt;The following configuration directives should be in &lt;code&gt;~/.zshrc&lt;/code&gt;. See the &lt;a href="https://github.com/topfunky/zsh-simple"&gt;full source&lt;/a&gt; for the complete setup.&lt;/p&gt;
      &lt;p&gt;Run these commands to load zsh&amp;#8217;s color variables. You&amp;#8217;ll be able to use readable values like &lt;code&gt;$fg[black]&lt;/code&gt; instead of cryptic ones like &lt;code&gt;\e[0m&lt;/code&gt;.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Colors&lt;/span&gt;&amp;#x000A;autoload -U colors&amp;#x000A;colors&amp;#x000A;setopt prompt_subst&lt;/pre&gt;&lt;/div&gt;
      &lt;a id='status'&gt;
        &lt;h3&gt;Last Command Status&lt;/h3&gt;
      &lt;/a&gt;
      &lt;p&gt;I first saw this technique in Pat Allan&amp;#8217;s shell. If the last command exited with a nonzero value, it will print a red Unicode frown: &lt;span style="color:red;"&gt;&#9785;&lt;/span&gt;. Successful commands will show a green smiley: &lt;span style="color:green;"&gt;&#9786;&lt;/span&gt;&lt;/p&gt;
      &lt;p&gt;It&amp;#8217;s a nice way to quickly see if tests failed or a compilation aborted.&lt;/p&gt;
      &lt;p&gt;And you&amp;#8217;re not limited to &lt;span class="caps"&gt;ASCII&lt;/span&gt;! Use the Unicode snowman, a skull and crossbones, or any other &lt;a href="http://en.wikipedia.org/wiki/Dingbat"&gt;dingbats character&lt;/a&gt;.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Save a smiley to a local variable if the last command exited with success.&lt;/span&gt;&amp;#x000A;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;smiley&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%(?,%{$fg[green]%}&#9786;%{$reset_color%},%{$fg[red]%}&#9785;%{$reset_color%})&amp;quot;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;a id='currentpath'&gt;
        &lt;h3&gt;Current Path&lt;/h3&gt;
      &lt;/a&gt;
      &lt;p&gt;On my local machine I want to show only what&amp;#8217;s necessary. So I don&amp;#8217;t show the current user, hostname, or anything other than the relative path that I&amp;#8217;m currently in.&lt;/p&gt;
      &lt;p&gt;In zsh, that&amp;#8217;s &lt;code&gt;%~&lt;/code&gt;.&lt;/p&gt;
      &lt;p&gt;Assign it to &lt;code&gt;PROMPT&lt;/code&gt; to set the left-hand part of the prompt. It occupies two lines: the path is on one line and the previously saved &lt;code&gt;smiley&lt;/code&gt; is on the next. &lt;code&gt;$reset_color&lt;/code&gt; is a &lt;code&gt;zsh&lt;/code&gt; variable that restores your default text color.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Show the relative path on one line, then the smiley.&lt;/span&gt;&amp;#x000A;&lt;span class="nv"&gt;PROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&amp;#x000A;&lt;span class="s1"&gt;%~&lt;/span&gt;&amp;#x000A;&lt;span class="s1"&gt;${smiley}  %{$reset_color%}&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;a id='gitbranch'&gt;
        &lt;h3&gt;Git Branch, SHA &amp; Dirty Status&lt;/h3&gt;
      &lt;/a&gt;
      &lt;p&gt;It&amp;#8217;s surprisingly difficult to get Git to tell you what branch it&amp;#8217;s on. I&amp;#8217;ve tried several scripts, including the multi-&lt;span class="caps"&gt;SCM&lt;/span&gt; &lt;a href="http://vc.gerg.ca/hg/vcprompt/"&gt;vcprompt&lt;/a&gt; (which worked well).&lt;/p&gt;
      &lt;p&gt;My current favorite is a Ruby script that prints all kinds of useful information about your Git setup:&lt;/p&gt;
      &lt;ul&gt;
      	&lt;li&gt;&lt;strong&gt;Current branch name&lt;/strong&gt;&lt;/li&gt;
      	&lt;li&gt;&lt;strong&gt;The current &lt;span class="caps"&gt;SHA&lt;/span&gt;&lt;/strong&gt; (7 characters of it). Useful for anytime you need to get out of trouble with &lt;code&gt;git reset --hard&lt;/code&gt;. See the PeepCode &lt;a href="https://peepcode.com/products/advanced-git"&gt;Advanced Git&lt;/a&gt; video for this and other Git tips.&lt;/li&gt;
      	&lt;li&gt;&lt;strong&gt;Rebase status&lt;/strong&gt; (to know if you&amp;#8217;re in the middle of a rebase)&lt;/li&gt;
      	&lt;li&gt;&lt;strong&gt;Dirty status&lt;/strong&gt; Have any tracked files been edited? A Unicode &#10007; is displayed if changes have been made but not committed.&lt;/li&gt;
      &lt;/ul&gt;
      &lt;p&gt;The &lt;a href="https://github.com/benhoskings/dot-files/blob/master/files/bin/git_cwd_info"&gt;original script&lt;/a&gt; is from Ben Hoskings(requires Ruby 1.9). I edited it to work on Ruby 1.8 and used a brief &lt;code&gt;git-current-branch&lt;/code&gt; script (&lt;a href="https://github.com/topfunky/zsh-simple/blob/master/bin/git-cwd-info.rb"&gt;source&lt;/a&gt;). The relevant edit is on the last three lines where it specifies a format and colors for the final display.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;RPROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%{$fg[white]%} $(~/.rvm/bin/rvm-prompt)$(~/bin/git-cwd-info.rb)%{$reset_color%}&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;p&gt;I chose to make the more important metadata stand out more. The Git branch name and dirty status are more important to me than the Ruby version or the current &lt;span class="caps"&gt;SHA&lt;/span&gt;, so they are a darker shade of grey. Ben uses an &lt;code&gt;@&lt;/code&gt; sign before the &lt;span class="caps"&gt;SHA&lt;/span&gt;, but I replaced it with whitespace.&lt;/p&gt;
      &lt;img src="/blog/2012/my-command-line-prompt/img/git-detail.png" alt="Ruby &amp;amp; Git metadata." title="Ruby &amp;amp; Git metadata." /&gt;&lt;p class="caption"&gt;Ruby &amp;amp; Git metadata.&lt;/p&gt;
      &lt;a id='rvmconfig'&gt;
        &lt;h3&gt;RVM Config&lt;/h3&gt;
      &lt;/a&gt;
      &lt;p&gt;The name of the current Ruby version as configured by &lt;acronym title="Ruby Version Manager"&gt;&lt;span class="caps"&gt;RVM&lt;/span&gt;&lt;/acronym&gt; is actually in the previous snippet. It calls &lt;code&gt;~/.rvm/bin/rvm-prompt&lt;/code&gt; and displays it at the left side of the right hand prompt.&lt;/p&gt;
      &lt;h2&gt;Put it Together&lt;/h2&gt;
      &lt;p&gt;The combined prompt looks like this.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;# Combined left and right prompt configuration.&lt;/span&gt;&amp;#x000A;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;smiley&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;%(?,%{$fg[green]%}&#9786;%{$reset_color%},%{$fg[red]%}&#9785;%{$reset_color%})&amp;quot;&lt;/span&gt;&amp;#x000A;&amp;#x000A;&lt;span class="nv"&gt;PROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&amp;#x000A;&lt;span class="s1"&gt;%~&lt;/span&gt;&amp;#x000A;&lt;span class="s1"&gt;${smiley}  %{$reset_color%}&amp;#39;&lt;/span&gt;&amp;#x000A;&amp;#x000A;&lt;span class="nv"&gt;RPROMPT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;%{$fg[white]%} $(~/.rvm/bin/rvm-prompt)$(~/bin/git-cwd-info.rb)%{$reset_color%}&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;p&gt;The important thing is to customize your own prompt and make it work the way you want it to!&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div id='buyscreencast'&gt;
  &lt;div class='row'&gt;
    &lt;div class='column'&gt;
      &lt;h2&gt;
        Learn the command line, Git, and other great stuff!
      &lt;/h2&gt;
      &lt;p&gt;Check out our &lt;a href="https://peepcode.com/products/meet-the-command-line"&gt;Meet the Command Line&lt;/a&gt; and &lt;a href="https://peepcode.com/products/advanced-command-line"&gt;Advanced Command Line&lt;/a&gt; screencasts, plus our newest &lt;a href="http://peepcode.com/products/advanced-git"&gt;Advanced Git&lt;/a&gt; tutorial.&lt;/p&gt;
      &lt;div id="buy"&gt;&lt;h2&gt;Command Line&lt;/h2&gt;&lt;p class="small"&gt;Get started.&lt;br /&gt;Only &lt;sup&gt;$&lt;/sup&gt;12!&amp;nbsp;&lt;a href="http://peepcode.com/products/meet-the-command-line"&gt;More Info&amp;hellip;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div id="buy"&gt;&lt;h2&gt;Adv Command&lt;/h2&gt;&lt;p class="small"&gt;Master it.&lt;br /&gt;Only &lt;sup&gt;$&lt;/sup&gt;12!&amp;nbsp;&lt;a href="http://peepcode.com/products/advanced-command-line"&gt;More Info&amp;hellip;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
      &lt;div id="buy"&gt;&lt;h2&gt;Advanced Git&lt;/h2&gt;&lt;p class="small"&gt;One hour video.&lt;br /&gt;Only &lt;sup&gt;$&lt;/sup&gt;12!&amp;nbsp;&lt;a href="http://peepcode.com/products/advanced-git"&gt;More Info&amp;hellip;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</content>
    <published>Thu Jan 05 21:00:00 +0000 2012</published>
  </entry>
  <entry>
    <title>Geek Gift Guide 2011</title>
    <link href="http://blog.peepcode.com/blog/2011/geek-gift-guide-2011" type="text/html" rel="alternate"/>
    <id>tag:blog.peepcode.com,2011-12-13:/blog/2011/geek-gift-guide-2011</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;This article is heavily styled and is best viewed at &lt;a href="http://blog.peepcode.com/blog/2011/geek-gift-guide-2011"&gt;PeepCode&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;div id='geek-gift'&gt;
  &lt;div class='row'&gt;
    &lt;div class='column grid_12'&gt;
      &lt;p&gt;We&amp;#8217;ve all seen the geek gift guides put out by major publications. Somehow &lt;em&gt;all&lt;/em&gt; geeks, regardless of their connection to technology, like star wars legos, rubix cubes, and light-up keychains. Seriously? Not here. Not us.&lt;/p&gt;
      &lt;p&gt;Many geeks appreciate well-designed, thoughtful products. We know this because it&amp;#8217;s our bottom line. So here&amp;#8217;s our gift guide for classy geeks.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row'&gt;
    &lt;div class='column align-center'&gt;
      &lt;div class='price-range'&gt;
        &lt;div class='left-round-border'&gt;
          Filter:
        &lt;/div&gt;
        &lt;a class='active' href='#all'&gt;
          All
        &lt;/a&gt;
        &lt;a href='#1-20'&gt;&lt;sup&gt;$&lt;/sup&gt;1&#8211;20
        &lt;/a&gt;
        &lt;a href='#20-60'&gt;&lt;sup&gt;$&lt;/sup&gt;20&#8211;60
        &lt;/a&gt;
        &lt;a href='#60-100'&gt;&lt;sup&gt;$&lt;/sup&gt;60&#8211;100
        &lt;/a&gt;
        &lt;a href='#100-200'&gt;&lt;sup&gt;$&lt;/sup&gt;100&#8211;200
        &lt;/a&gt;
        &lt;a class='right-round-border' href='#200-800'&gt;&lt;sup&gt;$&lt;/sup&gt;200&#8211;800
        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row gifts'&gt;
    &lt;div class='column grid_12'&gt;
      &lt;h2&gt;
        Gifts from
        &lt;a id='1-20'&gt;&lt;sup&gt;$&lt;/sup&gt;1-20
        &lt;/a&gt;
      &lt;/h2&gt;
    &lt;/div&gt;
    &lt;div class='column feature'&gt;
      &lt;a href='http://peepcode.com/gifts'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/peepcode-gift-single.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://peepcode.com/gifts'&gt;
          Single PeepCode Gift Card
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;12
        &lt;/span&gt;
        A single screencast for your developer friends or that up-and-coming youngster in your family who wants to get started with programming.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.amazon.com/Crowd-Complete-Season-One/dp/B001NOMOS8/'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/it-crowd.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.amazon.com/Crowd-Complete-Season-One/dp/B001NOMOS8/'&gt;
          The IT Crowd, Season 1
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;10
        &lt;/span&gt;
        Unfortunately, this is about stereotypical nerds. Fortunately, it&#8217;s awesomely hilarious.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='https://www.canoeonline.net/shop/inspect/worther-shorty-mechanical-pencil/2021'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/mechanical-pencil.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='https://www.canoeonline.net/shop/inspect/worther-shorty-mechanical-pencil/2021'&gt;
          Worther Shorty Mechanical Pencil
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;14
        &lt;/span&gt;
        Writing is much more fun with a beautiful pencil. Available in black, grey, or yellow.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='https://www.canoeonline.net/shop/inspect/field-notes-notebooks-state-fair-edition/2646'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/field-notes.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='https://www.canoeonline.net/shop/inspect/field-notes-notebooks-state-fair-edition/2646'&gt;
          Field Notes
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;10
        &lt;/span&gt;
        Now that smartphones have abandoned the stylus, there's nothing like paper and pen for brainstorming. Whether your field is a coffee shop or a bus, Field Notes are convenient and stylish.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.amazon.com/Wisdom-Crowds-James-Surowiecki/dp/0385721706/'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/wisdom-of-crowds.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.amazon.com/Wisdom-Crowds-James-Surowiecki/dp/0385721706/'&gt;
          The Wisdom of Crowds
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;11
        &lt;/span&gt;
        Both a classic and a quick read, this entertaining book is for entrepreneurs, sociologists, and deep thinkers of all kinds.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.theghostlystore.com/collections/goods/products/bluelounge-milo'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/milo.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.theghostlystore.com/collections/goods/products/bluelounge-milo'&gt;
          Milo
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;15
        &lt;/span&gt;
        An elegant stand for any smartphone with a smooth, hard surface.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='https://www.momastore.org/webapp/wcs/stores/servlet/ProductDisplay_Branch%20Earphone%20Splitter_10451_10001_111827_-1_26663_26666_111856'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/branch-splitter.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='https://www.momastore.org/webapp/wcs/stores/servlet/ProductDisplay_Branch%20Earphone%20Splitter_10451_10001_111827_-1_26663_26666_111856'&gt;
          Branch Earphone Splitter
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;10
        &lt;/span&gt;
        Split your music between three people. Useful for those cramped international plane flights to the next tech conference.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.surlatable.com/product/PRO-667766/Whisky-Stones,-Set-of-Nine'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/whisky-stones.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.surlatable.com/product/PRO-667766/Whisky-Stones,-Set-of-Nine'&gt;
          Whisky Stones
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;20
        &lt;/span&gt;
        These bad boys will keep your whisky chilled without watering it down? Oh, buddy.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.amazon.com/How-Booze-Exquisite-Cocktails-Unsound/dp/0061963305'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/how-to-booze.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.amazon.com/How-Booze-Exquisite-Cocktails-Unsound/dp/0061963305'&gt;
          How to Booze
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;20
        &lt;/span&gt;
        &lt;em&gt;Exquisite Cocktails and other Unsound Advice&lt;/em&gt; humorously suggests matching beverages for any social situation.
      &lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row gifts'&gt;
    &lt;div class='column grid_12'&gt;
      &lt;h2&gt;
        Gifts from
        &lt;a id='20-60'&gt;&lt;sup&gt;$&lt;/sup&gt;20-60
        &lt;/a&gt;
      &lt;/h2&gt;
    &lt;/div&gt;
    &lt;div class='column feature'&gt;
      &lt;a href='http://peepcode.com/gifts'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/peepcode-gift-5pack.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://peepcode.com/gifts'&gt;
          5-Pack Gift Card
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;55
        &lt;/span&gt;
        Give five screencasts to anyone, redeemable at any time.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://shop.peepcode.com/products/coffeescript-t-shirt'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/peepcodeshirt-coffeescript.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://shop.peepcode.com/products/coffeescript-t-shirt'&gt;
          CoffeeScript T-Shirt
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;26
        &lt;/span&gt;
        For that friend who loves CoffeeScript, or even just coffee.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://shop.peepcode.com/products/chris-wanstrath-t-shirt'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/peepcodeshirt-wanstrath.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://shop.peepcode.com/products/chris-wanstrath-t-shirt'&gt;
          Chris Wanstrath T-Shirt
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;26
        &lt;/span&gt;
        This one's a bit niche, but that's what makes the best gifts, right? A t-shirt featuring Chris Wanstrath, co-founder of GitHub.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.amazon.com/dp/B0042X8XQE/?tag=svpply01-20'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/powercup-mobile-inverter.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.amazon.com/dp/B0042X8XQE/?tag=svpply01-20'&gt;
          PowerCup Mobile Inverter
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;26
        &lt;/span&gt;
        Until Apple makes a power adapter for your car, this is the best way to stay energized on the road.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.mophie.com/product-p/2025_jpu-reserve-2.htm'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/juice-pack.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.mophie.com/product-p/2025_jpu-reserve-2.htm'&gt;
          Juice Pack Reserver
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;35
        &lt;/span&gt;
        We don't mind a keychain when it's this useful! Carry an extra charge for your portable Apple products.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.blessthisstuff.com/stuff/technology/computers/uboard-smart/'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/uboard-smart.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.blessthisstuff.com/stuff/technology/computers/uboard-smart/'&gt;
          UBoard Smart
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;49
        &lt;/span&gt;
        Keeping your desk orderly isn't quite as important as having a place for your phone, coffee, tea, and three USB devices.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.conranshop.co.uk/609968/MOSHI-MOSHI-POP-BLACK/Product'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/moshi-moshi-pop-black.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.conranshop.co.uk/609968/MOSHI-MOSHI-POP-BLACK/Product'&gt;
          MOSHI MOSHI Pop Black
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;40
        &lt;/span&gt;
        Make those serious business calls even more official. Also available in red, pink, green, and yellow.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.tortoisegeneralstore.com/online_store/index.php/by-category/crafts/braid-wood-puzzle.html'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/wood-puzzle.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.tortoisegeneralstore.com/online_store/index.php/by-category/crafts/braid-wood-puzzle.html'&gt;
          Braid Wood Puzzle
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;34
        &lt;/span&gt;
        A brain teaser in 6 or 12 pieces.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.lovescotch.com/p/pigs-nose-5-year-old'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/pigs-nose.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.lovescotch.com/p/pigs-nose-5-year-old'&gt;
          Pig's Nose 5 Year Scotch
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;44
        &lt;/span&gt;
        Not all scotch has to be serious. Recommended by our marketing department.
      &lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row gifts'&gt;
    &lt;div class='column grid_12'&gt;
      &lt;h2&gt;
        Gifts from
        &lt;a id='60-100'&gt;&lt;sup&gt;$&lt;/sup&gt;60-100
        &lt;/a&gt;
      &lt;/h2&gt;
    &lt;/div&gt;
    &lt;div class='column feature'&gt;
      &lt;a href='http://peepcode.com/gifts'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/peepcode-gift-10pack.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://peepcode.com/gifts'&gt;
          10-Pack Gift Card
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;99
        &lt;/span&gt;
        This gift won't collect dust in the bottom drawer!
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://coolmaterial.com/tech/wood-ipad-2-cases/'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/wood-case.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://coolmaterial.com/tech/wood-ipad-2-cases/'&gt;
          Wood iPad 2 Case
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;79
        &lt;/span&gt;
        Nothing goes together like machined aluminum and solid wood.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.etsy.com/listing/69589092/4-letter-pillows-inserts-included'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/scrabble-pillows.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.etsy.com/listing/69589092/4-letter-pillows-inserts-included'&gt;
          Four Scrabble Letter Pillows
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;98
        &lt;/span&gt;
        With letters in solid black felt.
      &lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row gifts'&gt;
    &lt;div class='column grid_12'&gt;
      &lt;h2&gt;
        Gifts from
        &lt;a id='100-200'&gt;&lt;sup&gt;$&lt;/sup&gt;100-200
        &lt;/a&gt;
      &lt;/h2&gt;
    &lt;/div&gt;
    &lt;div class='column feature'&gt;
      &lt;a href='http://peepcode.com/gifts'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/peepcode-gift-unlimited.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://peepcode.com/gifts'&gt;
          Unlimited Subscription Gift Card
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;199
        &lt;/span&gt;
        This one will keep a friend or family member occupied (and maybe even employed) until next year!
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://shop.creaturesofcomfort.us/yuetetrisl-shapepouch-red.aspx'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/tetris-pouch.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://shop.creaturesofcomfort.us/yuetetrisl-shapepouch-red.aspx'&gt;
          Tetris L-Shape Pouch
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;165
        &lt;/span&gt;
        "Extremely supple leather" and "lined in red velvet" should be all you need to know.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.unicahome.com/p23982/kikkerland/to-ca-wood-led-clock-by-kouji-iwasaki.html'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/wood-clock.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.unicahome.com/p23982/kikkerland/to-ca-wood-led-clock-by-kouji-iwasaki.html'&gt;
          To:Ca Wood LED Clock
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;150
        &lt;/span&gt;
        A natural contrast to all the stainless steel, titanium, and adamantium in your home.
      &lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row gifts'&gt;
    &lt;div class='column grid_12'&gt;
      &lt;h2&gt;
        Gifts from
        &lt;a id='200-800'&gt;&lt;sup&gt;$&lt;/sup&gt;200-800
        &lt;/a&gt;
      &lt;/h2&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.revo.co.uk/digital-radio/revo-heritage.php'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/heritage-radio.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.revo.co.uk/digital-radio/revo-heritage.php'&gt;
          Revo Renaissance Radio
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;357
        &lt;/span&gt;
        The ceiling of the Sistine Chapel may have turned out differently if Michaelangelo had access to thousands of Internet radio stations (plus a docking port).
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://store.apple.com/us/product/TX584ZM/A'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/bowers-wilkins-headphones.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://store.apple.com/us/product/TX584ZM/A'&gt;
          Bowers &amp; Wilkins P5 Headphones
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;300
        &lt;/span&gt;
        Soft and cushy on the ears, tiny for travel, beautiful looking, and noise isolating. Yes, yes, and yes.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.dwr.com/product/link-task-lamp-small.do'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/led-lamp.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.dwr.com/product/link-task-lamp-small.do'&gt;
          Link LED Task Lamp
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;350
        &lt;/span&gt;
        Move this guy anywhere. With 360&amp;deg; swivel, 15 high-power LED lights, and only 7.5 watts.
      &lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column item grid_6'&gt;
      &lt;a href='http://www.williams-sonoma.com/products/breville-espresso-machine-with-integrated-burr-grinder/'&gt;
        &lt;img src='geek-gift-guide-2011/imgs/espresso-maker.png' /&gt;
      &lt;/a&gt;
      &lt;p class='title'&gt;
        &lt;a href='http://www.williams-sonoma.com/products/breville-espresso-machine-with-integrated-burr-grinder/'&gt;
          Espresso Machine with Integrated Grinder
        &lt;/a&gt;
      &lt;/p&gt;
      &lt;p&gt;
        &lt;span class='price'&gt;&lt;sup&gt;$&lt;/sup&gt;800
        &lt;/span&gt;
        Run it on automatic for a cup in the morning and graduate to manual for an evening sip. An integrated grinder means maximum flavor every time.
      &lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div id='ribbons-bg'&gt;
  &amp;nbsp;
&lt;/div&gt;
</content>
    <published>Tue Dec 13 21:00:00 +0000 2011</published>
  </entry>
  <entry>
    <title>Free Ryan Singer UI Sketching Video</title>
    <link href="http://blog.peepcode.com/blog/2011/free-ryan-singer-ui-sketching-video" type="text/html" rel="alternate"/>
    <id>tag:blog.peepcode.com,2011-10-06:/blog/2011/free-ryan-singer-ui-sketching-video</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;This article is heavily styled and is best viewed at &lt;a href="http://blog.peepcode.com/blog/2011/free-ryan-singer-ui-sketching-video"&gt;PeepCode&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;div class='wrapper'&gt;
  &lt;div class='row'&gt;
    &lt;div class='column buy-above'&gt;
      &lt;a class='buttonify' href='http://peepcode.com/products/ryan-singer-ux'&gt;
        Read More &amp; Buy This Video
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class='wrapper'&gt;
  &lt;div class='video'&gt;
&lt;iframe src="http://player.vimeo.com/video/30160052?title=0&amp;amp;byline=0&amp;amp;portrait=0&amp;amp;color=ffffff" width="1000" height="600" frameborder="0" webkitAllowFullScreen allowFullScreen&gt;&lt;/iframe&gt;

  &lt;/div&gt;
&lt;/div&gt;
&lt;div class='wrapper'&gt;
  &lt;div class='row'&gt;
    &lt;div class='column article'&gt;
      &lt;h2&gt;
        Front-end Prototyping
      &lt;/h2&gt;
      &lt;p&gt;When we started the &lt;a href="https://peepcode.com/screencasts/play-by-play"&gt;Play by Play&lt;/a&gt; series, we wanted not only to learn how skilled back-end developers work, but also how front-end developers get work done.&lt;/p&gt;
      &lt;p&gt;Ryan Singer of 37signals was at the top of our list and he certainly delivered. We did an hour of &lt;a href="https://peepcode.com/products/ryan-singer-ux"&gt;sketching&lt;/a&gt; and an hour of &lt;a href="https://peepcode.com/products/ryan-singer-ii"&gt;prototyping&lt;/a&gt; with &lt;span class="caps"&gt;HTML&lt;/span&gt; and &lt;span class="caps"&gt;CSS&lt;/span&gt; (and even a bit of Rails 3.1).&lt;/p&gt;
      &lt;p&gt;Ryan&amp;#8217;s process is an incredible mix of back-end theory (such as test-driven development) and front-end utility (sketching and prototyping). It has already changed the way we do things at PeepCode and we think you&amp;#8217;ll like it too.&lt;/p&gt;
      &lt;p&gt;View a free ten minutes from the sketching session in the video above.&lt;/p&gt;
      &lt;p class='author'&gt;
        &lt;em&gt;
          production by
        &lt;/em&gt;
        Geoffrey Grosenbach
        &lt;em&gt;&amp;amp;&lt;/em&gt;
        Paula Lavalle
      &lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class='wrapper'&gt;
  &lt;div class='row'&gt;
    &lt;div class='column buy-above'&gt;
      &lt;a class='buttonify' href='http://peepcode.com/products/ryan-singer-ux'&gt;
        Read More &amp; Buy This Video
      &lt;/a&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class='wrapper end'&gt;
  &lt;div class='row'&gt;
    &lt;div class='column social'&gt;
      &lt;div class='tweet'&gt;
        &lt;a class='twitter-share-button' data-count='horizontal' href='https://twitter.com/share'&gt;
          Tweet
        &lt;/a&gt;
        &lt;script src='//platform.twitter.com/widgets.js' type='text/javascript'&gt;&lt;/script&gt;
      &lt;/div&gt;
      &lt;div id='fb-root'&gt;&lt;/div&gt;
      &lt;script type='text/javascript'&gt;
        //&lt;![CDATA[
          (function(d, s, id) {
            var js, fjs = d.getElementsByTagName(s)[0];
            if (d.getElementById(id)) {return;}
            js = d.createElement(s); js.id = id;
            js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
            fjs.parentNode.insertBefore(js, fjs);
          }(document, 'script', 'facebook-jssdk'));
        //]]&gt;
      &lt;/script&gt;
      &lt;div class='fb-like' data-href='http://peepcode.com/blog/2011/free-ryan-singer-ui-sketching-video' data-layout='button_count' data-send='false' data-show-faces='false' data-width='50'&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</content>
    <published>Thu Oct 06 23:00:00 +0000 2011</published>
  </entry>
  <entry>
    <title>My Avatar</title>
    <link href="http://blog.peepcode.com/blog/2011/my-avatar" type="text/html" rel="alternate"/>
    <id>tag:blog.peepcode.com,2011-07-06:/blog/2011/my-avatar</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;This article is heavily styled and is best viewed at &lt;a href="http://blog.peepcode.com/blog/2011/my-avatar"&gt;PeepCode&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;div class='row' id='avatars'&gt;
  &lt;div class='column'&gt;
    &lt;p id='author'&gt;
      by Geoffrey Grosenbach &lt;span class="amp"&gt;&amp;amp;&lt;/span&gt; Paula Lavalle
    &lt;/p&gt;
    &lt;ul id='circles'&gt;
      &lt;li id='circle1'&gt;
        &lt;img alt='Avatar' src='/blog/2011/my-avatar/circle1.jpg' /&gt;
      &lt;/li&gt;
      &lt;li id='circle2'&gt;
        &lt;img alt='Avatar' src='/blog/2011/my-avatar/circle2.jpg' /&gt;
      &lt;/li&gt;
      &lt;li id='circle3'&gt;
        &lt;img alt='Avatar' src='/blog/2011/my-avatar/circle3.jpg' /&gt;
      &lt;/li&gt;
      &lt;li id='circle4'&gt;
        &lt;img alt='Avatar' src='/blog/2011/my-avatar/circle4.jpg' /&gt;
      &lt;/li&gt;
      &lt;li id='circle5'&gt;
        &lt;img alt='Avatar' src='/blog/2011/my-avatar/circle5.jpg' /&gt;
      &lt;/li&gt;
      &lt;li class='bigun' id='circle6'&gt;
        &lt;img alt='Avatar' src='/blog/2011/my-avatar/circle6.jpg' /&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class='row' id='prose'&gt;
  &lt;div class='column'&gt;
    &lt;h2&gt;The Hooligan&lt;/h2&gt;
    &lt;p&gt;In 2004 I worked at a grade school that hosted a highly
    anticipated field day every year. I decided to paint my face
    with my team&amp;#8217;s flag for that year: South Africa.&lt;/p&gt;
    &lt;p&gt;For the next few weeks, kindergarteners told me they had
    nightmares because of it.&lt;/p&gt;
    &lt;p&gt;The following year, I coached the team representing the &lt;span class="caps"&gt;USA&lt;/span&gt;. I
    carefully painted a flag on my face, only later to realize that
    I had put the stars on the wrong side (damn mirrors!). Fortunately
    no one noticed since I had started a trend. Almost every kid
    arrived with some kind of paint splashed on their face: stars,
    hearts, stripes, camouflage.&lt;/p&gt;
    &lt;p&gt;I used a photo from that day as my avatar for the next few
    years, but I managed to lose the original. Instead of adopting
    an entirely new avatar, I decided it was time to recreate
    it&amp;#8230;but better.&lt;/p&gt;
    &lt;p&gt;A studio flash, a digital &lt;span class="caps"&gt;SLR&lt;/span&gt;, and some face crayons solved the
    problem. I&amp;#8217;m now the owner of what may be the world&amp;#8217;s first
    studio photograph taken purely for the purpose of being
    displayed at 48&amp;#215;48 on Twitter, Facebook, GitHub, and other
    services.&lt;/p&gt;
    &lt;p&gt;People frequently tell me &amp;#8220;You look nothing like your avatar.&amp;#8221;
    Hopefully that&amp;#8217;s a little less true now.&lt;/p&gt;
    &lt;cite&gt;Geoffrey Grosenbach (&lt;a href="http://twitter.com/topfunky"&gt;@topfunky&lt;/a&gt;)&lt;/cite&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div id='colophon'&gt;
  &lt;div class='row'&gt;
    &lt;h2&gt;
      &lt;img alt='Colophon' src='/blog/2011/my-avatar/colophon/colophon-title.png' /&gt;
    &lt;/h2&gt;
    &lt;div class='column' id='mask-notes'&gt;
      &lt;h3&gt;&lt;span class="caps"&gt;CSS&lt;/span&gt; Masks&lt;/h3&gt;
      &lt;p&gt;In order to achieve excruciatingly crisp curves around the
      images, we used &lt;span class="caps"&gt;CSS&lt;/span&gt; masks with &lt;span class="caps"&gt;SVG&lt;/span&gt; paths.&lt;/p&gt;
      &lt;p&gt;24-bit &lt;span class="caps"&gt;PNG&lt;/span&gt; images can be saved with transparency without the
      need for masks, but &lt;span class="caps"&gt;JPG&lt;/span&gt; photos can&amp;#8217;t. Using a compressed &lt;span class="caps"&gt;JPG&lt;/span&gt;
      image with a &lt;span class="caps"&gt;CSS&lt;/span&gt; mask gives you the best of both worlds.&lt;/p&gt;
      &lt;h4&gt;Webkit&lt;/h4&gt;
      &lt;p&gt;Webkit&amp;#8217;s masking is more full-featured than Firefox (see notes
      below). It can use &lt;span class="caps"&gt;SVG&lt;/span&gt; files straight from Adobe Illustrator
      and can stretch masks dynamically.&lt;/p&gt;
      &lt;p&gt;&lt;img src="/blog/2011/my-avatar/colophon/masks.jpg" title="CSS image mask" alt="CSS image mask" /&gt;&lt;/p&gt;
      &lt;p&gt;The &lt;span class="caps"&gt;HTML&lt;/span&gt; markup references square images (seen at left). A circular mask is
      applied. The result is an image that is opaque in the black
      parts of the mask and transparent in the other parts.&lt;/p&gt;
      &lt;ul&gt;
      	&lt;li&gt;An element can be masked directly, or an outer element can mask all the elements inside it.&lt;/li&gt;
      &lt;/ul&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;&amp;lt;li&amp;gt;&lt;/span&gt;&amp;#x000A;  &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;face.jpg&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&amp;#x000A;&lt;span class="nt"&gt;&amp;lt;/li&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;ul&gt;
      	&lt;li&gt;In Adobe Illustrator or another graphics application, draw a black shape and &amp;#8220;Save As&amp;#8221; &lt;span class="caps"&gt;SVG&lt;/span&gt;. You can use it directly in Webkit with no further modification.&lt;/li&gt;
      &lt;/ul&gt;
      &lt;ul&gt;
      	&lt;li&gt;Use the &lt;code&gt;-webkit-mask-box-image&lt;/code&gt; directive in &lt;span class="caps"&gt;CSS&lt;/span&gt; to specify the path to the &lt;span class="caps"&gt;SVG&lt;/span&gt; file. We found it easiest to use the &lt;code&gt;stretch&lt;/code&gt; option to expand the mask to fill the area covered by the element being masked. This also works better for animation since the mask grows as the image is resized.&lt;/li&gt;
      &lt;/ul&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(mask.svg)&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="n"&gt;stretch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;h4&gt;Firefox&lt;/h4&gt;
      &lt;p&gt;Firefox needs a slightly different &lt;span class="caps"&gt;SVG&lt;/span&gt; file and can&amp;#8217;t stretch the mask.&lt;/p&gt;
      &lt;ul&gt;
      	&lt;li&gt;Make a copy of the &lt;span class="caps"&gt;SVG&lt;/span&gt; file you used with Webkit. Open it in a text editor. Modify it to include a &lt;code&gt;mask&lt;/code&gt; element around the drawing directives. The &lt;code&gt;mask&lt;/code&gt; element should have an &lt;code&gt;id&lt;/code&gt; so you can refer to it in the next step (we used &lt;code&gt;avatar-mask&lt;/code&gt;).&lt;/li&gt;
      &lt;/ul&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c"&gt;&amp;lt;!-- Note: Simplified for educational purposes.  --&amp;gt;&lt;/span&gt;&amp;#x000A;&lt;span class="nt"&gt;&amp;lt;svg&amp;gt;&lt;/span&gt;&amp;#x000A;  &lt;span class="nt"&gt;&amp;lt;mask&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;avatar-mask&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;&amp;#x000A;    &lt;span class="nt"&gt;&amp;lt;circle&lt;/span&gt; &lt;span class="na"&gt;cx=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;cy=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;r=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;100&amp;quot;&lt;/span&gt; &lt;span class="na"&gt;fill=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;white&amp;quot;&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;&amp;#x000A;  &lt;span class="nt"&gt;&amp;lt;/mask&amp;gt;&lt;/span&gt;&amp;#x000A;&lt;span class="nt"&gt;&amp;lt;/svg&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;ul&gt;
      	&lt;li&gt;You also need to specify &lt;code&gt;fill="white"&lt;/code&gt; for the drawing directives (such as the &lt;code&gt;circle&lt;/code&gt; above).&lt;/li&gt;
      &lt;/ul&gt;
      &lt;ul&gt;
      	&lt;li&gt;Add a line to your &lt;span class="caps"&gt;CSS&lt;/span&gt;. Ask for a &lt;code&gt;mask&lt;/code&gt; and include the &lt;span class="caps"&gt;URL&lt;/span&gt; of the Firefox mask file. Append the &lt;code&gt;id&lt;/code&gt; of the &lt;code&gt;mask&lt;/code&gt; element (&lt;code&gt;avatar-mask&lt;/code&gt; in this example).&lt;/li&gt;
      &lt;/ul&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;box&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(mask.svg)&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="n"&gt;stretch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;  &lt;span class="c"&gt;/* Non-Webkit browsers */&lt;/span&gt;&amp;#x000A;  &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="sx"&gt;url(mask-firefox.svg#avatar-mask)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;p&gt;Because Firefox masks won&amp;#8217;t stretch with the element, we made
      a larger mask for the big version of the avatar. It makes the
      animation less elegant than the Webkit version, but it looks
      the same once the animation has completed.&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column' id='animation-notes'&gt;
      &lt;h3&gt;&lt;span class="caps"&gt;CSS&lt;/span&gt; Animation&lt;/h3&gt;
      &lt;p&gt;We started out thinking that we would need to use jQuery or
      Scriptaculous to animate the circles into the center when
      clicked. It turns out that &lt;span class="caps"&gt;CSS&lt;/span&gt; animations are supported in
      most modern browsers and make the code much easier.&lt;/p&gt;
      &lt;h4&gt;CoffeeScript&lt;/h4&gt;
      &lt;p&gt;Now that we know it, why not use
      &lt;a href="https://peepcode.com/products/coffeescript"&gt;CoffeeScript&lt;/a&gt;? We
      used it with jQuery to listen for a click on any of the images
      and add a &lt;span class="caps"&gt;CSS&lt;/span&gt; class. The class repositions the item to the
      center and makes it larger.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;jQuery&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&amp;#x000A;  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#circles li&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;click&lt;/span&gt; &lt;span class="nf"&gt;(event) -&amp;gt;&lt;/span&gt;&amp;#x000A;    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#circles li&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;removeClass&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bigun&amp;#39;&lt;/span&gt;&amp;#x000A;    &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;addClass&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;bigun&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;h4&gt;Animation&lt;/h4&gt;
      &lt;p&gt;Until two days ago, we thought &lt;span class="caps"&gt;CSS&lt;/span&gt; animation was a complicated
      system that would take weeks to figure out.&lt;/p&gt;
      &lt;p&gt;Animating it only took two lines.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;p&gt;The easiest way is to specify &lt;code&gt;all&lt;/code&gt; properties. When you add a
      &lt;span class="caps"&gt;CSS&lt;/span&gt; class to an element, all the new properties will
      animate. Otherwise, you can use a comma-delimited list of only
      the properties you want to animate: &lt;code&gt;opacity,left,right&lt;/code&gt;, etc.&lt;/p&gt;
      &lt;p&gt;You can also add the same directives for Firefox and Opera:&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;  &lt;span class="c"&gt;/* Webkit */&lt;/span&gt;&amp;#x000A;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;webkit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;&amp;#x000A;  &lt;span class="c"&gt;/* Firefox */&lt;/span&gt;&amp;#x000A;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;moz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;moz&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;&amp;#x000A;  &lt;span class="c"&gt;/* Opera */&lt;/span&gt;&amp;#x000A;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="err"&gt;o&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;property&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;  &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="err"&gt;o&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;transition&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;duration&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1s&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;h4&gt;See also&lt;/h4&gt;
      &lt;ul&gt;
      	&lt;li&gt;&lt;a href="http://www.webkit.org/blog/138/css-animation/"&gt;Official Webkit blog post&lt;/a&gt;&lt;/li&gt;
      &lt;/ul&gt;
      &lt;h3&gt;Other&lt;/h3&gt;
      &lt;p&gt;Sass was instrumental in positioning the list items in a
      circular pattern. After calculating everything, we were able
      to change the radius of the hexagon and even the sizes of the
      circles until they fit.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nt"&gt;li&lt;/span&gt;&lt;span class="nl"&gt;#circle1&lt;/span&gt;&amp;#x000A;  &lt;span class="nt"&gt;top&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;cy&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;hexagon_radius&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nt"&gt;0&lt;/span&gt;&lt;span class="nc"&gt;.866&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;radius&lt;/span&gt;&amp;#x000A;  &lt;span class="nt"&gt;left&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;cx&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;hexagon_radius&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nt"&gt;2&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="nt"&gt;radius&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;p&gt;Oh, and some photographs. We fitted a Nikon D7000 camera with
      a 50mm lens and hooked it to an inexpensive studio strobe and
      umbrella from &lt;a href="http://alienbees.com"&gt;AlienBees&lt;/a&gt;.&lt;/p&gt;
      &lt;p&gt;And of course, some face paint!&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
</content>
    <published>Wed Jul 06 00:00:00 +0000 2011</published>
  </entry>
  <entry>
    <title>CoffeeScript in Motion</title>
    <link href="http://blog.peepcode.com/blog/2011/coffeescript-in-motion" type="text/html" rel="alternate"/>
    <id>tag:blog.peepcode.com,2011-05-19:/blog/2011/coffeescript-in-motion</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;This article is heavily styled and is best viewed at &lt;a href="http://blog.peepcode.com/blog/2011/coffeescript-in-motion"&gt;PeepCode&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;div class='segment'&gt;
  &lt;div class='upper'&gt;
    &lt;h2&gt;In Motion&lt;/h2&gt;
    &lt;div id="buy"&gt;&lt;h2&gt;Learn it!&lt;/h2&gt;&lt;p class="small"&gt;One hour video.&lt;br /&gt;Only &lt;sup&gt;$&lt;/sup&gt;12!&amp;nbsp;&lt;a href="http://peepcode.com/products/coffeescript"&gt;More Info&amp;hellip;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
    &lt;div class='videobox'&gt;
      &lt;a href='http://peepcode.com/system/uploads/2011/blog/coffeescript/b-1-coffeescript-jquery/b-1-coffeescript-jquery.mov'&gt;
        &lt;img alt='A snippet of code' class='screenshot' src='/blog/2011/coffeescript-in-motion/b-1-coffeescript-jquery.jpg' /&gt;
      &lt;/a&gt;
      &lt;h5&gt;COFFEESCRIPT:&lt;/h5&gt;
      &lt;pre class='coffee'&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;jQuery&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&amp;#x000A;  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#entry&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
      &lt;h5&gt;JAVASCRIPT:&lt;/h5&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;jQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &amp;#x000A;  &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;#entry&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&amp;#x000A;&lt;span class="p"&gt;});&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;h3&gt;
      1. A simple function
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class='before'&gt;&amp;nbsp;&lt;/div&gt;
&lt;div id='content-overalls'&gt;
  &lt;div class='segment content'&gt;
    &lt;h4&gt;Engineering + Creativity&lt;/h4&gt;
    &lt;div class='column'&gt;
      &lt;p&gt;In his book &lt;em&gt;Rise of the Creative Class&lt;/em&gt;, Richard Florida defines a list of creative professions that includes graphic designers, sculptors, architects, and&amp;#8230;software writers.&lt;/p&gt;
      &lt;p&gt;It&amp;#8217;s hard to think of a better place to see creativity and engineering than in CoffeeScript, a little language that compiles to JavaScript.&lt;/p&gt;
      &lt;p&gt;CoffeeScript is beautiful. It&amp;#8217;s sensibly designed around syntactic indentation. It adds useful features to JavaScript. Most importantly, it&amp;#8217;s a very thin layer over JavaScript. For any line of CoffeeScript, one can easily predict the line of JavaScript that the compiler will emit.&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column'&gt;
      &lt;p&gt;CoffeeScript invents some good ideas and steals many others. The number one source I could identify for the most useful ideas in CoffeeScript? Perl.&lt;/p&gt;
      &lt;p&gt;Yes, Perl. The language that&amp;#8217;s guaranteed to produce an audible gasp if mentioned in civilized programming circles today. Yet for ten solid years, Perl was a petri dish of syntactic innovation. Extended regular expressions, destructuring assignment.&lt;/p&gt;
      &lt;p&gt;Which is why it&amp;#8217;s exciting to see syntactic experimentation happening with such vigor in CoffeeScript.&lt;/p&gt;
      &lt;p&gt;In these video snippets, you&amp;#8217;ll see how JavaScript and CoffeeScript compare.&lt;/p&gt;
      &lt;div id='prose-credits'&gt;
        &amp;mdash; Geoffrey Grosenbach
        &lt;div class='small'&gt;
          Design &amp; Motion Graphics by Paula Lavalle
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class='after'&gt;&amp;nbsp;&lt;/div&gt;
&lt;div id='video-overalls'&gt;
  &lt;div class='segment video'&gt;
    &lt;center&gt;
      &lt;img alt='' class='ornament' src='/blog/2011/coffeescript-in-motion/ornament.png' /&gt;
    &lt;/center&gt;
    &lt;h3 class='ondark'&gt;
      2. Jasmine&amp;#8217;s &amp;#8216;describe&amp;#8217; function with args
    &lt;/h3&gt;
    &lt;div class='videobox'&gt;
      &lt;a href='http://peepcode.com/system/uploads/2011/blog/coffeescript/b-2-coffeescript-jasmine/b-2-coffeescript-jasmine.mov'&gt;
        &lt;img alt='A snippet of code' class='screenshot' src='/blog/2011/coffeescript-in-motion/b-2-coffeescript-jasmine.jpg' /&gt;
      &lt;/a&gt;
      &lt;h5 class='ondark'&gt;COFFEESCRIPT:&lt;/h5&gt;
      &lt;pre class='coffee'&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;describe&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;constructor&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
      &lt;h5 class='ondark'&gt;JAVASCRIPT:&lt;/h5&gt;
      &lt;pre&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;constructor&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;&amp;#x000A;&lt;span class="p"&gt;});&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
    &lt;/div&gt;
    &lt;h3 class='ondark'&gt;
      3. The @ syntax for instance properties
    &lt;/h3&gt;
    &lt;div class='videobox'&gt;
      &lt;a href='http://peepcode.com/system/uploads/2011/blog/coffeescript/b-3-coffeescript-beforeEach/b-3-coffeescript-beforeEach.mov'&gt;
        &lt;img alt='A snippet of code' class='screenshot' src='/blog/2011/coffeescript-in-motion/b-3-coffeescript-beforeEach.jpg' /&gt;
      &lt;/a&gt;
      &lt;h5 class='ondark'&gt;COFFEESCRIPT:&lt;/h5&gt;
      &lt;pre class='coffee'&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;beforeEach&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&amp;#x000A;  &lt;span class="vi"&gt;@dish = &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Dish&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;Steak $18.99&amp;#39;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
      &lt;h5 class='ondark'&gt;JAVASCRIPT:&lt;/h5&gt;
      &lt;pre&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;beforeEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dish&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Dish&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Steak $18.99&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&amp;#x000A;&lt;span class="p"&gt;});&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
    &lt;/div&gt;
    &lt;div class='quotation'&gt;
      &lt;blockquote&gt;&amp;#8220;Everybody shows off&lt;br /&gt;And wants to look presentable&lt;br /&gt;But the fact of the matter&lt;br /&gt;Is that accidents are preventable.&amp;#8221; &lt;cite&gt;&amp;mdash; Buck 65&lt;/cite&gt;&lt;/blockquote&gt;
    &lt;/div&gt;
    &lt;h3 class='ondark'&gt;
      4. An instance method
    &lt;/h3&gt;
    &lt;div class='videobox'&gt;
      &lt;a href='http://peepcode.com/system/uploads/2011/blog/coffeescript/b-4-coffeescript-instance-method/b-4-coffeescript-instance-method.mov'&gt;
        &lt;img alt='A snippet of code' class='screenshot' src='/blog/2011/coffeescript-in-motion/b-4-coffeescript-instance-method.jpg' /&gt;
      &lt;/a&gt;
      &lt;h5 class='ondark'&gt;COFFEESCRIPT:&lt;/h5&gt;
      &lt;pre class='coffee'&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;add: &lt;/span&gt;&lt;span class="nf"&gt;(dish) -&amp;gt;&lt;/span&gt;&amp;#x000A;  &lt;span class="nx"&gt;@dishes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt; &lt;span class="nx"&gt;dish&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
      &lt;h5 class='ondark'&gt;JAVASCRIPT:&lt;/h5&gt;
      &lt;pre&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;Meal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prototype&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dish&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dishes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dish&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&amp;#x000A;&lt;span class="p"&gt;};&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
    &lt;/div&gt;
    &lt;h3 class='ondark'&gt;
      5. A full class with constructor
    &lt;/h3&gt;
    &lt;div class='videobox'&gt;
      &lt;a href='http://peepcode.com/system/uploads/2011/blog/coffeescript/b-5-coffeescript-class/b-5-coffeescript-class.mov'&gt;
        &lt;img alt='A snippet of code' class='screenshot' src='/blog/2011/coffeescript-in-motion/b-5-coffeescript-class.jpg' /&gt;
      &lt;/a&gt;
      &lt;h5 class='ondark'&gt;COFFEESCRIPT:&lt;/h5&gt;
      &lt;pre class='coffee'&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Money&lt;/span&gt;&amp;#x000A;  &lt;span class="nv"&gt;constructor: &lt;/span&gt;&lt;span class="nf"&gt;(rawString) -&amp;gt;&lt;/span&gt;&amp;#x000A;    &lt;span class="vi"&gt;@cents = &lt;/span&gt;&lt;span class="nx"&gt;@parseCents&lt;/span&gt; &lt;span class="nx"&gt;rawString&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
      &lt;h5 class='ondark'&gt;JAVASCRIPT:&lt;/h5&gt;
      &lt;pre&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nx"&gt;Money&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;Money&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parseCents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rawString&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&amp;#x000A;  &lt;span class="p"&gt;}&lt;/span&gt;&amp;#x000A;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;Money&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&amp;#x000A;&lt;span class="p"&gt;})();&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
    &lt;/div&gt;
    &lt;h3 class='ondark'&gt;
      6. Object literal
    &lt;/h3&gt;
    &lt;div class='videobox'&gt;
      &lt;a href='http://peepcode.com/system/uploads/2011/blog/coffeescript/b-6-coffeescript-json/b-6-coffeescript-json.mov'&gt;
        &lt;img alt='A snippet of code' class='screenshot' src='/blog/2011/coffeescript-in-motion/b-6-coffeescript-json.jpg' /&gt;
      &lt;/a&gt;
      &lt;h5 class='ondark'&gt;COFFEESCRIPT:&lt;/h5&gt;
      &lt;pre class='coffee'&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nv"&gt;toJSON: &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&amp;#x000A;  &lt;span class="nv"&gt;title: &lt;/span&gt;&lt;span class="nx"&gt;@title&lt;/span&gt;&amp;#x000A;  &lt;span class="nv"&gt;price: &lt;/span&gt;&lt;span class="nx"&gt;@price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
      &lt;h5 class='ondark'&gt;JAVASCRIPT:&lt;/h5&gt;
      &lt;pre&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;toJSON&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;    &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&amp;#x000A;    &lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&amp;#x000A;  &lt;span class="p"&gt;};&lt;/span&gt;&amp;#x000A;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/pre&gt;
    &lt;/div&gt;
    &lt;h4 class='buy-ondark'&gt;
      Intrigued?
      &lt;a href='http://peepcode.com/products/coffeescript'&gt;
        Buy the 75 minute video at PeepCode!
      &lt;/a&gt;
    &lt;/h4&gt;
    &lt;center&gt;
      &lt;img alt='' class='ornament end' src='/blog/2011/coffeescript-in-motion/ornament.png' /&gt;
    &lt;/center&gt;
  &lt;/div&gt;
&lt;/div&gt;
</content>
    <published>Thu May 19 18:00:00 +0000 2011</published>
  </entry>
  <entry>
    <title>R.I.P. Ruby Hash Rocket Syntax 1993-2010</title>
    <link href="http://blog.peepcode.com/blog/2011/rip-ruby-hash-rocket-syntax" type="text/html" rel="alternate"/>
    <id>tag:blog.peepcode.com,2011-01-05:/blog/2011/rip-ruby-hash-rocket-syntax</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;This article is heavily styled and is best viewed at &lt;a href="http://blog.peepcode.com/blog/2011/rip-ruby-hash-rocket-syntax"&gt;PeepCode&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;div class='column article'&gt;
  &lt;p&gt;&lt;img src="/blog/2011/rip-ruby-hash-rocket-syntax/comic.jpg" id="comic" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column prose'&gt;
  &lt;p&gt;The hash rocket is dead. In Ruby 1.9, hashes whose keys are symbols can be built with a single colon.&lt;/p&gt;
  &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="p"&gt;{&lt;/span&gt;&amp;#x000A;  &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&amp;#x000A;  &lt;span class="n"&gt;dr_nic&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;The Comedian&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&amp;#x000A;  &lt;span class="n"&gt;ttl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&amp;#x000A;&lt;span class="p"&gt;}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
  &lt;p&gt;No longer will you need to remember different syntax when switching between JavaScript and Ruby (or even Python!). And you&amp;#8217;ll save at least three characters every time.&lt;/p&gt;
  &lt;p&gt;It&amp;#8217;s one more reason to start using Ruby 1.9!&lt;/p&gt;
  &lt;p&gt;Please update your code accordingly.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column footnotes'&gt;
  &lt;p&gt;Learn more about Ruby 1.9 at &lt;a href="https://peepcode.com/screencasts/ruby"&gt;PeepCode&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Inspiration from the &lt;a href="http://www.flickr.com/photos/21633523@N03/2697517999/"&gt;opening panels&lt;/a&gt; of &lt;a href="http://en.wikipedia.org/wiki/Watchmen"&gt;The Watchmen&lt;/a&gt;.&lt;/p&gt;
  &lt;p&gt;Comment on this post at &lt;a href="http://news.ycombinator.com/item?id=2073004"&gt;Hacker News&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</content>
    <published>Wed Jan 05 22:00:00 +0000 2011</published>
  </entry>
  <entry>
    <title>Happy Holidays from PeepCode</title>
    <link href="http://blog.peepcode.com/blog/2010/happy-holidays" type="text/html" rel="alternate"/>
    <id>tag:blog.peepcode.com,2010-12-23:/blog/2010/happy-holidays</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;This article is heavily styled and is best viewed at &lt;a href="http://blog.peepcode.com/blog/2010/happy-holidays"&gt;PeepCode&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;div class='column article'&gt;
  &lt;p&gt;Thanks for making 2010 the biggest year yet at PeepCode!&lt;/p&gt;
  &lt;p&gt;We&amp;#8217;re excited about keeping you informed and on top of your game. We&amp;#8217;ve got big plans for 2011!&lt;/p&gt;
&lt;/div&gt;
</content>
    <published>Thu Dec 23 01:00:00 +0000 2010</published>
  </entry>
  <entry>
    <title>Rethinking Rails 3 Controllers and Routes</title>
    <link href="http://blog.peepcode.com/blog/2010/rethinking-rails-3-routes" type="text/html" rel="alternate"/>
    <id>tag:blog.peepcode.com,2010-06-02:/blog/2010/rethinking-rails-3-routes</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;This article is heavily styled and is best viewed at &lt;a href="http://blog.peepcode.com/blog/2010/rethinking-rails-3-routes"&gt;PeepCode&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;div class='column' id='disclaimer'&gt;
  &lt;p&gt;&lt;span class="caps"&gt;DISCLAIMER&lt;/span&gt;: Reg Braithwaite delivered this quote in a completely different context&lt;sup class="footnote"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt;, but I think it&amp;#8217;s applicable to the design of almost any software &lt;span class="caps"&gt;API&lt;/span&gt;. Illustration by Mike Rohde.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column article'&gt;
  &lt;div class='row'&gt;
    &lt;div class='column' id='intro'&gt;
      &lt;p&gt;The &lt;strong&gt;Rails router&lt;/strong&gt; has been written and rewritten at least four
      times&lt;sup class="footnote"&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;, including a recent rewrite for the upcoming Rails
      3. The syntax is now more concise.&lt;/p&gt;
      &lt;p&gt;But never mind making it shorter! It&amp;#8217;s time for a &lt;strong&gt;final
      rewrite&lt;/strong&gt;: Let&amp;#8217;s get rid of it altogether!&lt;/p&gt;
      &lt;p&gt;Let&amp;#8217;s &lt;strong&gt;get rid&lt;/strong&gt; of the &lt;strong&gt;seven controller actions&lt;/strong&gt;: &lt;code&gt;index&lt;/code&gt;,
      &lt;code&gt;show&lt;/code&gt;, &lt;code&gt;new&lt;/code&gt;, &lt;code&gt;create&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;update&lt;/code&gt; and &lt;code&gt;delete&lt;/code&gt;. Their
      meaning is blurred in the context of &lt;span class="caps"&gt;REST&lt;/span&gt;. They&amp;#8217;re an unhelpful
      layer between programmer and protocol.&lt;/p&gt;
      &lt;p&gt;Let&amp;#8217;s get rid of the trivial but &lt;strong&gt;cumbersome mental
      translation&lt;/strong&gt; you have to do everytime you want to think about
      the &lt;span class="caps"&gt;HTTP&lt;/span&gt; &lt;code&gt;GET&lt;/code&gt; method, the &lt;span class="caps"&gt;URL&lt;/span&gt;, the &lt;code&gt;index&lt;/code&gt; action, and the
      &lt;code&gt;plural_path&lt;/code&gt; &lt;span class="caps"&gt;URL&lt;/span&gt; helper.&lt;/p&gt;
      &lt;p&gt;Let&amp;#8217;s get rid of &lt;strong&gt;duplicate functionality&lt;/strong&gt; already implemented
      in the controller. If you need to redirect, take action based
      on the user agent, or examine headers, that should be done in
      a controller!&lt;/p&gt;
      &lt;p&gt;And let&amp;#8217;s &lt;strong&gt;start thinking in URLs&lt;/strong&gt;, resources, and APIs instead of
      doing image caching in models or asset bundling in
      view helpers. That&amp;#8217;s the controller&amp;#8217;s job. It scales better, too.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row'&gt;
    &lt;div class='column' id='manifesto'&gt;
      
      &lt;ul&gt;
      	&lt;li&gt;Routes are unnecessary configuration.&lt;/li&gt;
      	&lt;li&gt;The seven standard controller actions are legacy.&lt;/li&gt;
      	&lt;li&gt;Become intimate with your URLs &amp;#8211; don&amp;#8217;t abstract them away.&lt;/li&gt;
      	&lt;li&gt;Decrease the distance between thought and implementation.&lt;/li&gt;
      	&lt;li&gt;Let the controller do its job.&lt;/li&gt;
      &lt;/ul&gt;
      &lt;li&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row problems first'&gt;
    &lt;div class='column diagram'&gt;
      &lt;h2&gt;Get Back to Thinking in URLs&lt;/h2&gt;
      &lt;p&gt;A big part of the problem with a routing layer is that it
      abstracts the developer away from the URLs that define the
      application. This leads to poor &lt;span class="caps"&gt;API&lt;/span&gt; designs and convoluted
      solutions to otherwise easy problems.&lt;/p&gt;
      &lt;p&gt;This epiphany came while writing a few Sinatra
      applications. The exact &lt;span class="caps"&gt;URL&lt;/span&gt; for a handler sits right in
      front of my eyes as I write the code for it. I can&amp;#8217;t ignore it.&lt;/p&gt;
      &lt;p&gt;As a result, I find myself spending more time thinking about
      how my URLs are designed. Should I be serving &lt;span class="caps"&gt;JSON&lt;/span&gt; from the
      same controller that serves the &lt;span class="caps"&gt;HTML&lt;/span&gt; interface, or should it
      be organized separately?&lt;/p&gt;
      &lt;p&gt;In contrast, you can write an entire Rails application without
      ever looking at a &lt;span class="caps"&gt;URL&lt;/span&gt;. The design of URLs is delegated to the
      framework, out of sight and out of mind.&lt;/p&gt;
      &lt;p&gt;This isn&amp;#8217;t to say that we need to lose the good parts of how
      Rails works with URLs. &lt;span class="caps"&gt;URL&lt;/span&gt; helper methods like
      &lt;code&gt;pancake_path(:id)&lt;/code&gt; are a great idea for reducing duplication
      and typos. They could be implemented apart from any router.&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column prose'&gt;
      &lt;blockquote&gt;&amp;#8220;I love URLs. I dream about them at night. I think about them before I think about anything else.&amp;#8221; &lt;cite&gt;&amp;mdash; Adrian Holovaty, co-creator of Django&lt;/cite&gt;&lt;/blockquote&gt;&lt;p class="caption"&gt;* From &lt;a href="http://matthewbuchanan.name/post/79527495/i-love-urls"&gt;Webstock 2009&lt;/a&gt;&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row problems'&gt;
    &lt;div class='column diagram'&gt;
      &lt;h2&gt;Retire the Seven Action Names&lt;/h2&gt;
      &lt;p&gt;It has been three years since the seven controller actions had
      any immediate meaning. The &lt;span class="caps"&gt;API&lt;/span&gt; no longer adds to the
      programmer&amp;#8217;s understanding of the tasks at hand.&lt;/p&gt;
      &lt;p&gt;Experienced programmers know that inline comments mark code
      that&amp;#8217;s too confusing or too clever.&lt;/p&gt;
      &lt;p&gt;Yet every Rails controller is generated with two lines of
      repetitive comments for every action. That&amp;#8217;s a code smell! And
      a failure of &lt;span class="caps"&gt;API&lt;/span&gt; design.&lt;/p&gt;
      &lt;p&gt;Every Rails developer must memorize the table at right,
      mapping &lt;span class="caps"&gt;HTTP&lt;/span&gt; method and &lt;span class="caps"&gt;URL&lt;/span&gt; to the controller action name. If
      we can get rid of the action name, the rest of the table is
      already self-explanatory.&lt;/p&gt;
      &lt;p&gt;So instead of going through this extra syntactical layer, let&amp;#8217;s
      deal directly with &lt;span class="caps"&gt;GET&lt;/span&gt;, &lt;span class="caps"&gt;POST&lt;/span&gt;, &lt;span class="caps"&gt;PUT&lt;/span&gt;, and &lt;span class="caps"&gt;DELETE&lt;/span&gt;. (Suggestions follow.)&lt;/p&gt;
      &lt;p&gt;You can tell this is a great idea because it&amp;#8217;s the way unit tests
      already work! Let&amp;#8217;s bring this syntax back to the controller and
      complete the &lt;span class="caps"&gt;API&lt;/span&gt;.&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column prose'&gt;
      &lt;table&gt;
      	&lt;tr&gt;
      		&lt;th&gt;Method&lt;/th&gt;
      		&lt;th&gt;&lt;span class="caps"&gt;URL&lt;/span&gt;&lt;/th&gt;
      		&lt;th&gt;Action&lt;/th&gt;
      		&lt;th&gt;Helper&lt;/th&gt;
      	&lt;/tr&gt;
      	&lt;tr&gt;
      		&lt;td&gt;&lt;span class="caps"&gt;GET&lt;/span&gt;&lt;/td&gt;
      		&lt;td&gt;/pancakes&lt;/td&gt;
      		&lt;td class="action"&gt;index&lt;/td&gt;
      		&lt;td&gt;pancakes_path&lt;/td&gt;
      	&lt;/tr&gt;
      	&lt;tr class="odd"&gt;
      		&lt;td&gt; &lt;span class="caps"&gt;GET&lt;/span&gt;&lt;/td&gt;
      		&lt;td&gt;/pancakes/:id&lt;/td&gt;
      		&lt;td class="action"&gt;show&lt;/td&gt;
      		&lt;td&gt;pancake_path(:id)&lt;/td&gt;
      	&lt;/tr&gt;
      	&lt;tr&gt;
      		&lt;td&gt;&lt;span class="caps"&gt;GET&lt;/span&gt;&lt;/td&gt;
      		&lt;td&gt;/pancakes/new&lt;/td&gt;
      		&lt;td class="action"&gt;new&lt;/td&gt;
      		&lt;td&gt;new_pancake_path&lt;/td&gt;
      	&lt;/tr&gt;
      	&lt;tr class="odd"&gt;
      		&lt;td&gt; &lt;span class="caps"&gt;POST&lt;/span&gt;&lt;/td&gt;
      		&lt;td&gt;/pancakes&lt;/td&gt;
      		&lt;td class="action"&gt;create&lt;/td&gt;
      		&lt;td&gt;pancakes_path&lt;/td&gt;
      	&lt;/tr&gt;
      	&lt;tr&gt;
      		&lt;td&gt;&lt;span class="caps"&gt;GET&lt;/span&gt;&lt;/td&gt;
      		&lt;td&gt;/pancakes/:id/edit&lt;/td&gt;
      		&lt;td class="action"&gt;edit&lt;/td&gt;
      		&lt;td&gt;edit_pancake_path(:id)&lt;/td&gt;
      	&lt;/tr&gt;
      	&lt;tr class="odd"&gt;
      		&lt;td&gt; &lt;span class="caps"&gt;PUT&lt;/span&gt;&lt;/td&gt;
      		&lt;td&gt;/pancakes/:id&lt;/td&gt;
      		&lt;td class="action"&gt;update&lt;/td&gt;
      		&lt;td&gt;pancake_path(:id)&lt;/td&gt;
      	&lt;/tr&gt;
      	&lt;tr&gt;
      		&lt;td&gt;&lt;span class="caps"&gt;DELETE&lt;/span&gt;&lt;/td&gt;
      		&lt;td&gt;/pancakes/:id&lt;/td&gt;
      		&lt;td class="action"&gt;destroy&lt;/td&gt;
      		&lt;td&gt;pancake_path(:id)&lt;/td&gt;
      	&lt;/tr&gt;
      &lt;/table&gt;
      &lt;p class="highlight-file-link small"&gt;&lt;a href="/blog/2010/rethinking-rails-3-routes/controller-comments.rb"&gt;controller-comments.rb&lt;/a&gt;&lt;/p&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# GET /pancakes&lt;/span&gt;&amp;#x000A;&lt;span class="c1"&gt;# GET /pancakes.xml&lt;/span&gt;&amp;#x000A;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;&amp;#x000A;&lt;span class="k"&gt;end&lt;/span&gt;&amp;#x000A;&amp;#x000A;&lt;span class="c1"&gt;# POST /pancakes&lt;/span&gt;&amp;#x000A;&lt;span class="c1"&gt;# POST /pancakes.xml&lt;/span&gt;&amp;#x000A;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&amp;#x000A;&lt;span class="k"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;p class="highlight-file-link small"&gt;&lt;a href="/blog/2010/rethinking-rails-3-routes/test-with-http-method.rb"&gt;test-with-http-method.rb&lt;/a&gt;&lt;/p&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="nb"&gt;test&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;should create pancake&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&amp;#x000A;  &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="ss"&gt;:create&lt;/span&gt;&amp;#x000A;  &lt;span class="n"&gt;assert_redirected_to&lt;/span&gt; &lt;span class="n"&gt;pancake_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&amp;#x000A;&lt;span class="k"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row problems last'&gt;
    &lt;div class='column diagram'&gt;
      &lt;h2&gt;Assets Are Resources&lt;/h2&gt;
      &lt;p&gt;Thinking in URLs helps you solve web-related problems in the
      right way.&lt;/p&gt;
      &lt;p&gt;Exhibit A: If you deploy to a site whose view fragments are
      already cached in memcached, it&amp;#8217;s likely that Rails&amp;#8217; asset
      caching view helpers will not be called and &lt;span class="caps"&gt;CSS&lt;/span&gt; bundles will
      not be generated.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# Caching shouldn&amp;#39;t happen here&lt;/span&gt;&amp;#x000A;&lt;span class="n"&gt;stylesheet_link_tag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;c&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&amp;#x000A;                    &lt;span class="ss"&gt;:cache&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;p&gt;This whole problem is easily solved by &lt;em&gt;using controllers to
      do what they do best&lt;/em&gt;. Views and helpers should not generate
      &lt;span class="caps"&gt;URL&lt;/span&gt;-based resources.&lt;/p&gt;
      &lt;p&gt;The task of combining several &lt;span class="caps"&gt;CSS&lt;/span&gt; files into one file and
      caching them to disk is &lt;em&gt;exactly&lt;/em&gt; the kind of task controllers
      are built to do&lt;sup class="footnote"&gt;&lt;a href="#fn3"&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column prose'&gt;
      &lt;img src="/blog/2010/rethinking-rails-3-routes/asset-urls.png" alt="Controllers should generate and cache assets, not view helpers." title="Controllers should generate and cache assets, not view helpers." /&gt;&lt;p class="caption"&gt;Controllers should generate and cache assets, not view helpers.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row'&gt;
    &lt;div class='column half'&gt;
      &lt;h2&gt;Idea 1: Sinatra&lt;/h2&gt;
      &lt;p&gt;There are many ways the controller &lt;span class="caps"&gt;API&lt;/span&gt; could be
      improved. Existing attempts have failed to achieve wide
      adoption because they have tried to handle controllers, views,
      and models all at once&lt;sup class="footnote"&gt;&lt;a href="#fn4"&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
      &lt;p&gt;Instead, I think a more limited, controller-only approach
      could work better.&lt;/p&gt;
      &lt;p&gt;The first is already in wide use: Sinatra.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# Sinatra-style handler&lt;/span&gt;&amp;#x000A;&lt;span class="n"&gt;get&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/api/v1/report/:id&amp;quot;&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&amp;#x000A;  &lt;span class="c1"&gt;# ...&lt;/span&gt;&amp;#x000A;&lt;span class="k"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;p&gt;Sinatra is arguably the most widely replicated Ruby web
      framework, having inspired implementations in Node.js,
      Clojure, &lt;span class="caps"&gt;PHP&lt;/span&gt;, Scala, and many other languages.&lt;/p&gt;
      &lt;p&gt;Part of the problem with writing a routing &lt;span class="caps"&gt;API&lt;/span&gt; is finding a
      way to describe multiple URLs in a single string. This problem
      is solved if you handle each &lt;span class="caps"&gt;URL&lt;/span&gt; on its own.&lt;/p&gt;
      &lt;p&gt;There&amp;#8217;s no middle routing layer with arbitrary action
      names. &lt;span class="caps"&gt;HTTP&lt;/span&gt; method and &lt;span class="caps"&gt;URL&lt;/span&gt; are all you need (but handlers can
      filter on the user agent or other header information).&lt;/p&gt;
      &lt;p&gt;Thanks to Rack, Sinatra apps can be embedded in Rails
      applications. Or, Carl Lerche is writing a Rails 3 plugin that
      provides this syntax to Rails controllers&lt;sup class="footnote"&gt;&lt;a href="#fn5"&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
    &lt;/div&gt;
    &lt;div class='column half'&gt;
      &lt;h2&gt;Idea 2: Method, Member, Collection&lt;/h2&gt;
      &lt;p&gt;Jamis Buck introduced an implementation of &lt;span class="caps"&gt;REST&lt;/span&gt; as a plugin
      &lt;em&gt;four years&lt;/em&gt; ago. Yet unlike other areas of Rails that have
      seen massive improvements, Rails&amp;#8217; implementation of &lt;span class="caps"&gt;REST&lt;/span&gt; is
      basically the same as it was in Rails 1.2.&lt;/p&gt;
      &lt;p&gt;A halfway approach could combine elements of the Rails 3
      router syntax with the class method style of configuration
      that&amp;#8217;s already familiar to Rails developers.&lt;/p&gt;
      &lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="c1"&gt;# Class method and HTTP-style methods.&lt;/span&gt;&amp;#x000A;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ReportsController&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;AppController&lt;/span&gt;&amp;#x000A;  &lt;span class="n"&gt;before_filter&lt;/span&gt; &lt;span class="ss"&gt;:authenticate&lt;/span&gt;&amp;#x000A;  &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;&amp;quot;/api/v1/reports(/:id)&amp;quot;&lt;/span&gt;&amp;#x000A;&amp;#x000A;  &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:collection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;&amp;#x000A;  &lt;span class="k"&gt;end&lt;/span&gt;&amp;#x000A;&amp;#x000A;  &lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:member&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&amp;#x000A;  &lt;span class="k"&gt;end&lt;/span&gt;&amp;#x000A;&amp;#x000A;  &lt;span class="n"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:member&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&amp;#x000A;  &lt;span class="k"&gt;end&lt;/span&gt;&amp;#x000A;&amp;#x000A;&lt;span class="k"&gt;end&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;
      &lt;p&gt;Variations on this syntax could easily accomodate nested
      resources, singleton resources, or other custom &lt;span class="caps"&gt;URL&lt;/span&gt; schemes.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row'&gt;
    &lt;div class='column' id='conclusion'&gt;
      &lt;h2&gt;Conclusion&lt;/h2&gt;
      &lt;p&gt;For several years, Rails has charged forward and defined new,
      innovative syntaxes for writing web applications. It&amp;#8217;s time for
      it to happen again.&lt;/p&gt;
      &lt;p&gt;An improved syntax could &lt;strong&gt;get rid of stale controller
      actions&lt;/strong&gt;, &lt;strong&gt;reduce confusion&lt;/strong&gt;, &lt;strong&gt;reduce duplication&lt;/strong&gt;, and
      &lt;strong&gt;improve&lt;/strong&gt; the way we think about solving technical problems
      with web applications.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class='row'&gt;
    &lt;div class='column' id='addendum'&gt;
      &lt;h2&gt;Reactions&lt;/h2&gt;
      &lt;p class="caption"&gt;Thanks to &lt;a href="http://reginald.braythwayt.com/"&gt;Reg Braithwaite&lt;/a&gt; and &lt;a href="http://benhoskin.gs/"&gt;Ben Hoskings&lt;/a&gt; for feedback on this article.&lt;/p&gt;&lt;p&gt;&lt;a href="http://benhoskin.gs/"&gt;Ben Hoskings&lt;/a&gt; said&lt;/p&gt;
      &lt;blockquote&gt;
      &lt;p&gt;I think the mere fact that a controller can be generated means that code shouldn&amp;#8217;t be there. There&amp;#8217;s no intelligence in code that can be generated from a single resource name.&lt;/p&gt;
      &lt;/blockquote&gt;
      &lt;blockquote&gt;
      &lt;p&gt;I think it&amp;#8217;s doubly important because once you free the controller from having to implement the specifics of each action (like models doesn&amp;#8217;t have to implement the specifics of &lt;code&gt;#save&lt;/code&gt;), you have a lot more room to raise the abstraction level and start getting declarative.&lt;/p&gt;
      &lt;/blockquote&gt;
      &lt;blockquote&gt;
      &lt;p&gt;I think making the controller more declarative is probably the end goal. Instead of the bulk of each action being an imperative mess, the controller can be heavier on the class-level configuration that&amp;#8217;s really proven itself in the model (associations, scopes, plugin configuration, etc.).&lt;/p&gt;
      &lt;/blockquote&gt;
      &lt;p&gt;The &lt;code&gt;provides&lt;/code&gt; class-level configuration directive in Merb/Rails 3 is a signal that controllers can head in this direction.&lt;/p&gt;
      &lt;p&gt;Kyle Neath gives several &lt;a href="http://warpspire.com/posts/url-design/"&gt;useful guidelines&lt;/a&gt; in detail for thinking about &lt;span class="caps"&gt;URL&lt;/span&gt; design.&lt;/p&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;
&lt;div class='column footnotes'&gt;
  &lt;p&gt;Thoughts and reactions? Reply to &lt;a href="http://twitter.com/topfunky"&gt;@topfunky&lt;/a&gt; on Twitter, write a blog post of your own, or comment at &lt;a href="http://news.ycombinator.com/item?id=1398654"&gt;Hacker News&lt;/a&gt;.&lt;/p&gt;
  &lt;p class="footnote" id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; &lt;a href="http://www.infoq.com/presentations/braithwaite-rewrite-ruby"&gt;Video&lt;/a&gt; of Reg Braithwaite at RubyFringe. Quote is about 15:30 in.&lt;/p&gt;
  &lt;p class="footnote" id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; The original version by David Heinemeier Hansson, then by
  Ulysses, then by Koz and Jamis Buck (together), and most recently
  by Yehuda Katz, Josh Peek, and the Rails 3 team.&lt;/p&gt;
  &lt;p class="footnote" id="fn3"&gt;&lt;sup&gt;3&lt;/sup&gt; &lt;a href="/blog/2010/rethinking-rails-3-routes/javascripts_controller.rb"&gt;Sample controller code&lt;/a&gt;. Versioning and expiration of assets are easily solved by storing a
  version number in the application and appending it to the link
  tag.&lt;/p&gt;
  &lt;p class="footnote" id="fn4"&gt;&lt;sup&gt;4&lt;/sup&gt; See &lt;a href="http://github.com/benhoskings/hammock"&gt;hammock&lt;/a&gt; by Ben Hoskings, &lt;a href="http://github.com/hcatlin/make_resourceful"&gt;make_resourceful&lt;/a&gt; by Hampton Catlin and &lt;a href="http://github.com/jamesgolick/resource_controller"&gt;resource_controller&lt;/a&gt; by James Golick.&lt;/p&gt;
  &lt;p class="footnote" id="fn5"&gt;&lt;sup&gt;5&lt;/sup&gt; Carl Lerche&amp;#8217;s &lt;a href="http://github.com/carllerche/astaire"&gt;Astaire&lt;/a&gt; plugin.&lt;/p&gt;
&lt;/div&gt;
</content>
    <published>Wed Jun 02 16:00:00 +0000 2010</published>
  </entry>
  <entry>
    <title>Am I the Only One Who Uses a Text Editor to Edit Files?</title>
    <link href="http://blog.peepcode.com/blog/2010/file-navigation-in-text-editors" type="text/html" rel="alternate"/>
    <id>tag:blog.peepcode.com,2010-03-25:/blog/2010/file-navigation-in-text-editors</id>
    <content type="html">&lt;p&gt;&lt;strong&gt;This article is heavily styled and is best viewed at &lt;a href="http://blog.peepcode.com/blog/2010/file-navigation-in-text-editors"&gt;PeepCode&lt;/a&gt;!&lt;/strong&gt;&lt;/p&gt;&lt;div class='column article'&gt;
  &lt;img src="/blog/2010/file-navigation-in-text-editors/mockup-cropped.png" alt="Files should be navigable by file, class, or method name and show metadata useful for distinguishing between similar files (mockup)." title="Files should be navigable by file, class, or method name and show metadata useful for distinguishing between similar files (mockup)." /&gt;&lt;p class="caption"&gt;Files should be navigable by file, class, or method name and show metadata useful for distinguishing between similar files (mockup).&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column article split'&gt;
  &lt;p&gt;If I had no experience with computers and were to guess which
  group of people had the best software tools to do their job, I
  would guess &amp;#8220;computer programmers.&amp;#8221;&lt;/p&gt;
  &lt;p&gt;And if I were to guess what task would have been extensively
  optimized, I would guess &amp;#8220;opening files.&amp;#8221;&lt;/p&gt;
  &lt;p&gt;If you &lt;em&gt;are&lt;/em&gt; a programmer, you know that I would be wrong.&lt;/p&gt;
  &lt;p&gt;Last summer, Dave Peck wrote about his hopes for a modern,
  progressive, text editor.&lt;sup class="footnote"&gt;&lt;a href="#fn1"&gt;1&lt;/a&gt;&lt;/sup&gt; I&amp;#8217;d like to focus on one missing feature
  that&amp;#8217;s absolutely possible today: powerful file navigation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column article title'&gt;
  &lt;p&gt;&lt;img src="/blog/2010/file-navigation-in-text-editors/title-what-i-want.png" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column feature first'&gt;
  &lt;p&gt;&lt;img src="/blog/2010/file-navigation-in-text-editors/icon-keyboard.png" alt="" /&gt;&lt;/p&gt;
  &lt;h4&gt;Keyboard&lt;/h4&gt;
  &lt;p&gt;Perform any navigation task without touching the mouse.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column feature'&gt;
  &lt;p&gt;&lt;img src="/blog/2010/file-navigation-in-text-editors/icon-fuzzy.png" alt="" /&gt;&lt;/p&gt;
  &lt;h4&gt;Fuzzy Search&lt;/h4&gt;
  &lt;p&gt;Find files by typing only a few letters.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column feature'&gt;
  &lt;p&gt;&lt;img src="/blog/2010/file-navigation-in-text-editors/icon-path.png" alt="" /&gt;&lt;/p&gt;
  &lt;h4&gt;Paths&lt;/h4&gt;
  &lt;p&gt;Search includes folder names (relative to the project).&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column feature'&gt;
  &lt;p&gt;&lt;img src="/blog/2010/file-navigation-in-text-editors/icon-metadata.png" alt="" /&gt;&lt;/p&gt;
  &lt;h4&gt;Metadata&lt;/h4&gt;
  &lt;p&gt;File modification date and &lt;span class="caps"&gt;SCM&lt;/span&gt; status aid in file picking.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column feature'&gt;
  &lt;p&gt;&lt;img src="/blog/2010/file-navigation-in-text-editors/icon-beautiful.png" alt="" /&gt;&lt;/p&gt;
  &lt;h4&gt;Beautiful&lt;/h4&gt;
  &lt;p&gt;Terminal raster graphics don&amp;#8217;t count! I want &lt;span class="caps"&gt;GUI&lt;/span&gt; beauty.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column article split'&gt;
  &lt;p&gt;As every Vim user knows, most of one&amp;#8217;s time spent in a text editor is
  spent &lt;em&gt;editing&lt;/em&gt;, not writing (this is why &lt;em&gt;Normal&lt;/em&gt; mode in Vim is
  the one you use for navigation and editing).&lt;/p&gt;
  &lt;p&gt;For most programming tasks, editing involves opening several files at
  once and switching between them (e.g. &lt;span class="caps"&gt;HTML&lt;/span&gt;/JavaScript/&lt;span class="caps"&gt;CSS&lt;/span&gt;).&lt;/p&gt;
  &lt;p&gt;I&amp;#8217;m talking about three tasks:&lt;/p&gt;
  &lt;ul&gt;
  	&lt;li&gt;Open any file on the computer.&lt;/li&gt;
  	&lt;li&gt;Open any file in the current project.&lt;/li&gt;
  	&lt;li&gt;Activate a file that&amp;#8217;s already open in another tab.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p&gt;And yet most text editors offload these important tasks to the
  operating system or implement half-hearted custom solutions. Even
  worse, third-party plugins frequently implement file-jumping
  functionality for different frameworks with unique, cryptic key
  mappings (e.g. between implementation and test or controller and
  view template).&lt;/p&gt;
  &lt;p&gt;This is a core task! Editors should approach it with the same
  innovation and care they spend on basic text entry.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column article title'&gt;
  &lt;p&gt;&lt;img src="/blog/2010/file-navigation-in-text-editors/title-current-editors.png" alt="" /&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column editor'&gt;
  &lt;h5&gt;TextMate&lt;/h5&gt;
  &lt;div class="keyboard"&gt;Keyboard&lt;/div&gt;
  &lt;div class="fuzzy"&gt;Fuzzy&lt;/div&gt;
  &lt;div class="beautiful"&gt;Beautiful&lt;/div&gt;
  &lt;p&gt;Command-T with &lt;strong&gt;fuzzy search was revolutionary&lt;/strong&gt; and was one of the
  main reasons I bought a copy of TextMate. &lt;strong&gt;But it breaks down&lt;/strong&gt; for
  projects with many files of the same name (such as Ruby on Rails).&lt;/p&gt;
  &lt;img src="/blog/2010/file-navigation-in-text-editors/textmate-index.png" alt="There&amp;#8217;s no way to filter by directory." title="There&amp;#8217;s no way to filter by directory." /&gt;&lt;p class="caption"&gt;There&amp;#8217;s no way to filter by directory.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Tabs are even worse&lt;/strong&gt;. I frequently open more tabs than can fit on
   my screen, which means that &lt;strong&gt;both usability and the extra tabs
   get thrown out the window&lt;/strong&gt;. The tab menu can only be accessed
   with the mouse and becomes a human-powered binary search of an
   unsorted list.&lt;sup class="footnote"&gt;&lt;a href="#fn2"&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column editor'&gt;
  &lt;h5&gt;Xcode&lt;/h5&gt;
  &lt;div class="keyboard"&gt;Keyboard&lt;/div&gt;
  &lt;div class="beautiful"&gt;Beautiful&lt;/div&gt;
  &lt;p&gt;Xcode&amp;#8217;s &lt;em&gt;Open Quickly&lt;/em&gt; command (Command-Shift-D) only works with
  &lt;strong&gt;the exact file name&lt;/strong&gt; starting with the &lt;strong&gt;first letter.&lt;/strong&gt;&lt;/p&gt;
  &lt;img src="/blog/2010/file-navigation-in-text-editors/xcode-open-quickly.png" alt="Xcode&amp;#8217;s Open Quickly dialog" title="Xcode&amp;#8217;s Open Quickly dialog" /&gt;&lt;p class="caption"&gt;Xcode&amp;#8217;s Open Quickly dialog&lt;/p&gt;&lt;p&gt;Many Cocoa developers &lt;strong&gt;store all their code files in the root
  directory&lt;/strong&gt; of the project and rely on Xcode&amp;#8217;s virtual directories
  for organization, which is the only reason it&amp;#8217;s even &lt;strong&gt;barely
  usable&lt;/strong&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column editor'&gt;
  &lt;h5&gt;Emacs&lt;/h5&gt;
  &lt;div class="keyboard"&gt;Keyboard&lt;/div&gt;
  &lt;div class="fuzzy"&gt;Fuzzy&lt;/div&gt;
  &lt;div class="path"&gt;Path&lt;/div&gt;
  &lt;p&gt;Emacs is the &lt;strong&gt;closest to satisfying&lt;/strong&gt; my requirements.&lt;/p&gt;
  &lt;p&gt;The &lt;code&gt;ido-menu&lt;/code&gt; provides &lt;strong&gt;fuzzy search, including pathnames&lt;/strong&gt;. Chris
  Wanstrath&amp;#8217;s textmate.el plugin&lt;sup class="footnote"&gt;&lt;a href="#fn3"&gt;3&lt;/a&gt;&lt;/sup&gt; wraps it in even more useful
  functionality, such as autodiscovery of a project root based on
  the existence of a &lt;code&gt;.git&lt;/code&gt; directory.&lt;/p&gt;
  &lt;p&gt;&lt;strong&gt;Open buffers&lt;/strong&gt; (similar to tabs) can be searched for by name (&lt;code&gt;C-x b&lt;/code&gt;) or in a list (&lt;code&gt;C-x C-b&lt;/code&gt;).&lt;/p&gt;
  &lt;p&gt;But the inline menu is an &lt;strong&gt;ugly&lt;/strong&gt; paragraph.&lt;/p&gt;
  &lt;img src="/blog/2010/file-navigation-in-text-editors/emacs-find.png" alt="A powerful search hidden behind a mess of text." title="A powerful search hidden behind a mess of text." /&gt;&lt;p class="caption"&gt;A powerful search hidden behind a mess of text.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column article'&gt;
  &lt;blockquote&gt;&amp;#8220;The only solution I can think of, so far,&lt;br /&gt;Is to smash out the windows with a crowbar.&amp;#8221; &lt;cite&gt;&amp;mdash; Buck 65&lt;/cite&gt;&lt;/blockquote&gt;
&lt;/div&gt;
&lt;div class='column article prototype'&gt;
  &lt;p&gt;Once you start thinking about making file navigation better, the
  ideas flow freely. Could a dialog &lt;strong&gt;search on class or method
  names&lt;/strong&gt; instead of just filenames? What about a free-form search for
  times and classes such as &amp;#8220;&lt;code&gt;yesterday Bacon#save&lt;/code&gt;&amp;#8221;?&lt;/p&gt;
  &lt;p&gt;This article started with &lt;strong&gt;pain&lt;/strong&gt;, developed into an &lt;strong&gt;idea&lt;/strong&gt;, and ended up as an &lt;strong&gt;unexpected prototype&lt;/strong&gt; implemented in MacRuby. I&amp;#8217;m using it daily and am fine-tuning the interaction, visuals, features, and performance.&lt;/p&gt;
  &lt;p&gt;The app is now available as &lt;a href="http://peepcode.com/products/peepopen"&gt;PeepOpen&lt;/a&gt; with a beautiful icon. Works with TextMate, Emacs, and MacVim.&lt;/p&gt;
  &lt;p&gt;For other updates, follow @peepcode on Twitter &lt;a href="http://twitter.com/peepcode"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column article prototype-image'&gt;
  &lt;img src="/blog/2010/file-navigation-in-text-editors/fuzzy-window-screenshot.png" alt="The initial prototype performs a fuzzy search on paths and lists file modification dates." title="The initial prototype performs a fuzzy search on paths and lists file modification dates." /&gt;&lt;p class="caption"&gt;The initial prototype performs a fuzzy search on paths and lists file modification dates.&lt;/p&gt;
&lt;/div&gt;
&lt;div class='column footnotes'&gt;
  &lt;p&gt;You can contribute your own froth over the design and content of this article with the Neanderthals at &lt;a href="http://news.ycombinator.com/item?id=1219401"&gt;Hacker News&lt;/a&gt;.&lt;/p&gt;
  &lt;p class="footnote" id="fn1"&gt;&lt;sup&gt;1&lt;/sup&gt; Dave Peck sends supplication to &lt;a href="http://davepeck.org/2009/05/14/dear-osx-editor-gods/"&gt;the text editor gods&lt;/a&gt;.&lt;/p&gt;
  &lt;p class="footnote" id="fn2"&gt;&lt;sup&gt;2&lt;/sup&gt; The &lt;a href="http://code.leadmediapartners.com/"&gt;RubyAMP&lt;/a&gt; bundle for TextMate shows a simple list of open windows, but without fuzzy search.&lt;/p&gt;
  &lt;p class="footnote" id="fn3"&gt;&lt;sup&gt;3&lt;/sup&gt; Chris Wanstrath&amp;#8217;s &lt;a href="http://github.com/defunkt/textmate.el"&gt;textmate.el&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;
</content>
    <published>Thu Mar 25 12:00:00 +0000 2010</published>
  </entry>
</feed>

