I’m working on a project where I think I’ll be using a parser library so I’ve been looking at the options. One thing I’ve noticed is that treetop is installed when Rails is installed. I didn’t know why, though, so I looked around.

First I looked at the Gemfile.lock. Had I known the format I would have found out my answer more quickly. I didn’t, though, and so when I found my first result for treetop, I stopped. It showed treetop below specs in the hierarchy.

GEM
  remote: http://rubygems.org/
  specs:
    # ...snip...
    thor (0.14.6)
    tilt (1.3.3)
    treetop (1.4.10)
      polyglot
      polyglot (>= 0.3.1)
    tzinfo (0.3.30)
    uglifier (1.0.3)

The next thing I did was run find . -iname '*.treetop' in ~/.rbenv. It found the following results:

(mbp) ~/.rbenv/versions/1.9.2-p290 $ find . -iname '*.treetop'
./lib/ruby/gems/1.9.1/gems/erector-0.8.3/lib/erector/erect/rhtml.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/address_lists.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/content_disposition.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/content_location.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/content_transfer_encoding.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/content_type.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/date_time.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/envelope_from.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/message_ids.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/mime_version.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/phrase_lists.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/received.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/rfc2045.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/rfc2822.treetop
./lib/ruby/gems/1.9.1/gems/mail-2.3.0/lib/mail/parsers/rfc2822_obsolete.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/examples/lambda_calculus/arithmetic.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/examples/lambda_calculus/lambda_calculus.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/lib/treetop/compiler/metagrammar.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/spec/compiler/test_grammar.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/spec/compiler/test_grammar_do.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/spec/composition/a.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/spec/composition/b.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/spec/composition/c.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/spec/composition/d.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/spec/composition/f.treetop
./lib/ruby/gems/1.9.1/gems/treetop-1.4.10/spec/composition/subfolder/e_includes_c.treetop
(mbp) ~/.rbenv/versions/1.9.2-p290 $

Aha, so there are numerous treetop files in actionmailer! I have my answer. Seems like a good use of a parser, plus those may be worth using as examples.

Then I took another look at a Gemfile.lock from a rails project, and saw that it was plainly listed there. I just didn’t see it and didn’t keep looking after I found one.

GEM
  remote: http://rubygems.org/
  specs:
    XMLCanonicalizer (1.0.1)
      log4r (>= 1.0.4)
    actionmailer (3.1.1)
      actionpack (= 3.1.1)
      mail (~> 2.3.0)
  # ...snip...

I noticed something: Gemfile.lock doesn’t show an arbitrarily nested hierarchy; instead it shows a list of gems and their dependencies, where the list of gems includes all gems. Then, separately at the end of the file, it shows the top-level gems from the Gemfile.

To see a deeply nested, a graph could be constructed from the Gemfile.lock, using the two nesting levels under specs as an adjacency list.

In the last couple of years I’ve witnessed a disturbing trend: developers adopting free Heroku as their only means of hosting side projects. More disturbingly, I operated this way myself for a couple of years. (Yes, freemium can be a trap for customers just like it can be a trap for businesses.)

Heroku has five megabytes for database space, which often sounds like it ought to be enough when it isn’t. Want auditing and comments? Nah, that’ll take up too much space. Its single dyno free plan serves one request at a time. The next steps up are twenty dollars a month and five cents an hour for databases and dynos, respectively. These aren’t that expensive for a major project, but for several side projects it quickly adds up.

I realized this and switched back to running a VPS, this time on Zerigo, which I pay for annually. There is no limit to the number of apps I have. Concurrent requests are supported. They can use the same databases. Database backups are free and uncomplicated. I’m also happy to be outside of the cloud oligopoly that seems to be forming.

Besides that, it’s fun! I get to try niche language platforms. Node.js was building steam long before Heroku supported it, and it still doesn’t support websockets. It’s not hard to find, with a little thinking, other interesting platforms to try. How about Racket or Factor? Or setting up your own Lucene server, or a web server that uses the git command line tool? Those can’t (easily) be run with Heroku.

I find anecdotally that most developers don’t have their own websites or non-trivial side projects. I only have the first, but I can sense that my personal website is helping me prepare to launch non-trivial side projects. I’ve done very little work to set up this server, yet despite tweeting about it and having visitors and occasional commenters, it stays up. That gives me the confidence I need to launch something bigger.

My plea to other developers (and aspiring developers) out there is to draw parallels between programming and other creative works and find out how much you could responsibly be spending for hosting side projects, and then realize that there’s no reason you shouldn’t have at least a VPS.

Today I read a great post that happens to be on a Posterous blog, and I wanted to send my kudos to the author. Feeling lazy, I clicked Posterous’ version of a Like button, which is a heart with a tooltip that says “Unlike this post” when I hover over it.

A few short minutes later, I saw a comment notification in my email inbox.

Posterous has this feature where people who leave comments receive notifications when people post additional comments. This way, people will see replies to their comments.

It does the same when people like posts, though. But the main reason for wanting to see comments doesn’t exist when people like posts. People generally do not reply to likes, though I admit I’ve seen it happen once or twice.

The lesson in this is that default actions software takes should be based on user intent, and that this is especially important when it’s a loud interaction like sending an email.

I’ll go further and say that this is one of the major pros to having threaded discussions in blog comments. DISQUS does this and they’re very wise to do it. They only send me email notifications when someone specifically replies to one of my comments. If I commented on Posterous posts nearly as often as I did on DISQUS widgets I’d have email notifications turned off for Posterous comments by now.

One final note: I posted a test comment without realizing it would get emailed instantly and that I didn’t know whether or not I can delete comments on Posterous (I can’t), and it got deleted soon afterward. Apparently the blog owner was close to his email. ;)

I wrote a script to delete URLs containing a string from Chrome’s history. It works for me. I don’t understand everything that it does, though, so it may have serious flaws. Use at your own risk.

# Removing history entries from Chrome that contain a search phrase
# Exit out of Chrome first
# Back up files and do this at your own risk

# gem install sqlite3 && gem install sequel

require 'sequel'

search_string = 'reddit'

# Delete history cache files
path = File.expand_path('~/Library/Application Support/Google/Chrome/Default')
cache_dirs = Dir.entries(path).select {|dir| dir != 'History' && dir.index('History') == 0}.map {|dir| File.join path, dir}
cache_dirs.each {|dir| File.delete dir}

# Delete matching history from sqlite3
DB = Sequel.sqlite File.join(path, 'History')
matching_urls = DB[:urls].filter(:url.like("%#{search_string}%"))
puts %Q[Deleting #{matching_urls.count} urls matching "#{search_string}"]
matching_urls.delete

I really like sqlite and Sequel.

Rails 3.1 has a serialize function that can take a custom column coder. A custom coder needs to have dump and load methods set, or else it will be recognized as a required type for the built-in YAML coder called YAMLColumn.

While the JSON class has the two required methods, it doesn’t allow specifying a default. So I created a custom coder. I don’t know where the best file and module locations to put the class in are, so I won’t include them here. This is the class, though:

class JSONColumn
  def initialize(default={})
    @default = default
  end

  # this might be the database default and we should plan for empty strings or nils
  def load(s)
    s.present? ? JSON.load(s) : @default.clone
  end

  # this should only be nil or an object that serializes to JSON (like a hash or array)
  def dump(o)
    JSON.dump(o || @default)
  end
end

Since load and dump are instance methods, an instance of JSONColumn needs to be passed rather than the class. Here’s an example that works for me inside of the rails console:

class Person < ActiveRecord::Base
  validate :name, :pets, :presence => true
  serialize :pets, JSONColumn.new([])
end

Update: Added .clone to the load method. HT @miyagawa.

I just googled something I’ve always wanted to know how to do in vim, and was surprised how quickly I found the answer.

In vim, there are separate modes for searching and commands. This generally works well as they have separate completion buffers and since I do them a lot, it keeps my command history from cluttering up my search history and vice versa. The area where I’ve wished that they were unified is when I want to convert from a search to a substitution expression. Normally in vim you do search expressions in search mode and command expressions in command mode. For example, if I wanted to search for trailing whitespace I might type:

/\s\s*

If I want to replace it with an empty string through the whole file I might type:

:%s/\s\s*//g

I can’t remove the / at the front of the command line with a backspace and replace it with a colon, so until I learned the tip I’m about to reveal I had to retype it. No longer.

The StackOverflow answer I found for the query, Convert vim / search to search and replace without retyping regular expression, suggests this remarkably simple technique:

You can type

/search_term

and then

:%s/<ctrl-r>// etc

where you actually press ctrl+r and then / to insert the search term.

It works! No longer do I desire for search and command modes to be unified.

There’s nothing new about expressing XML in a significant-indentation format. Here’s Slim next to one from 2001.

Simple Outline XML (2001)

html>
    head>
        title> My Home Page
    body>
        h1> Contact Details
        p>  I can be contacted at
            a>  href=mailto:me@myplace.net 
                this address
            except when on vacation.

Wikipedia Article

Slim (2010)

html
  head
    title My Home Page
  body
    h1 Contact Details
    p I can be contacted at
      a href="mailto:me@myplace.net" this address
      except when on vacation.

They’re quite similar. I find Slim a bit more comfortable in a ruby environment because it’s a bit more terse and uses two spaces like Ruby code does. It also is a templating language too. (In fact, I’m not sure there are converters going in both directions between XML/HTML and non-templated Slim. It could make a nice addition.)

I find vim’s :lcd command to be quite useful. For a long time I didn’t use it, mainly because I didn’t understand how it works.

First, using it is simple. It works just like :cd. You type :lcd path/to/directory in command mode. The path is relative to the current directory, so :lcd .., :lcd ~/Desktop, and :lcd /etc/apache2 all work.

The :lcd command changes the path of the current window. The current window is the current frame within the current tab. Now, what’s really neat, is that a new window (created from commands such as :sp and :tabedit) gets the local directory of the window it’s created from.

Most plugins respect it. Both Command-T and ack.vim search within the local current directory. Another plugin, fugitive, bases its commands on the git repository of the current file so it works smoothly with different local directories as well.

Bang commands (like :!cp README.md ~/Desktop) also use the local current directory.

Finally, after using it for a while it gets easy to tell which directory I’m in. The status line displays the path of the current file based on the local current directory, so if I know where the current file is I can quickly figure out where the local current directory is.

I used it the other day with bundle show to dig through the source of two dependencies of my Rails project to better understand them.

If you use vim and haven’t got in the habit of using :lcd I highly recommend it. If you use another editor and wish it handled working in multiple directories gracefully, consider giving vim a shot!

…and I like the new .on() and .off() API for setting up events.

I wrote some code that uses it, just for practice.

$.fn.tree = function(data) {
  var $el = $(this),
      html = [];
  
  function renderNode(node) {
    if (typeof node === "object") {
      html.push("<ul>");
      for (var key in node) {
        if (node.hasOwnProperty(key)) {
          html.push("<li><strong>" + key + ": </strong>");
          html.push(typeof node[key] == "object" ? renderNode(node[key]) : node[key]);
          html.push("</li>");
        }
      }
      html.push("</ul>");
    }
  }
  
  renderNode(data);
  $el.html(html.join(""));
  
  $el.on('click', 'strong', function() {
    $(this).closest('li').find('ul').toggle(200);
  });
};

$("<div>").appendTo("body").tree({
  name: {
    first: "Benjamin",
    last: "Atkin"
  },
  location: {
    city: "Boulder",
    state: "CO"
  },
  accounts: {
    social: {
      twitter: "http://twitter.com/benatkin",
      facebook: "http://facebook.com/atkin",
      gplus: "http://gplus.to/benatkin",
      identica: "http://identi.ca/benatkin",
      rstatus: "http://rstat.us/bat"
    },
    creative: {
      github: "http://github.com/benatkin",
      blog: "http://benatkin.com/"
    }
  }
});

Nothing too fancy.

Repositoryjquery
Ownerjquery

I knew this was coming before the Mac App Store was announced. Few believed it back then. When Apple first announced its Mac App Store, more believed it. Now that Apple has set a deadline for sandboxing, some people still don’t believe it.

I believe that I should be allowed control over my computers. This is not dependent on the distinction between client and server, or between web and native. I also don’t buy the argument that it’s different when talking about so-called appliances like the iPad, which are really just crippled general-purpose computers.

One of the first things I’m going to do about it is to switch to something other than Mac OS X or Windows for desktop computing.