Custom Textmate Commands
April 1st, 2008
Textmate is a pretty decent editor for OSX. I'm not in love with it, but we use it frequently at Elevator Up.
There is a plethora of plugins for Textmate to ease editing in different contexts, but sometimes you want to hack you're own commands.
For small scripting tasks, I tend to continue to use ruby. So I enjoy it when I can continue using it for the commands.
You can typically use this shell for a ruby command, and your printed output gets replaced within Textmate:
#!/usr/bin/env ruby
$: << ENV['TM_SUPPORT_PATH'] + '/lib'
input_from_tm = STDIN.read
puts "hello world!"
Here is an example of code block toggling for Markdown.
#!/usr/bin/env ruby
$: << ENV['TM_SUPPORT_PATH'] + '/lib'
s = STDIN.read
ends_with_newline = s != s.chomp
lines = s.split("\n")
lines.each_with_index do |s, index|
s =~ /^(\t)?(.*)/
if $1
print "#{$2}"
else
print "\t#{$2}"
end
print "\n" if index != lines.size - 1
end
print "\n" if ends_with_newline
And a screenshot to include the Textmate command options:
Using Capistrano 1.4 with 2.x
March 31st, 2008
At Elevator Up we typically use Capistrano for deploying our applications. Though I do have a bookmark to investigate Vlad when I get some time.
We've been a bit slow to upgrade to Capistrano 2.x, and have a lot of existing applications that depend upon Capistrano 1.4 for deployment.
One tactic we've taken is to write a custom script to explicitly use 1.4 in conjunction with 2.x. A minor hack from the original, and we have:
#!/usr/bin/env ruby
begin
require 'rubygems'
gem 'capistrano', '<= 1.4.1'
rescue LoadError
# no rubygems to load, so we fail silently
end
require 'capistrano/cli'
Capistrano::CLI.execute!
I threw this into a script called cap1.4 in /usr/local and can now do:
illian:~ zach$ cap1.4 -V
Capistrano v1.4.1
illian:~ zach$ cap -V
Capistrano v2.1.0
Obviously, a better approach would be to freeze in the capistrano gems per project, and access them via RAILS_ROOT/script/cap, but that too has been time sensitive. Notice a trend here?
Commonly overlooked usage of named routes
March 30th, 2008
Given a route :
ActionController::Routing::Routes.draw do |map|
map.foo "foo/:first/:second", :controller => "foo", :action => "something"
end
Obviously you can pass in :first and :second via:
foo_path(:first => "the first param", :second => "the second param")
However, for a more concise call, you can accomplish the same via:
foo_path("the first param", "the second param")
It's not explicitly documented, but you end up doing the same thing with nested resource paths
Watch Star Wars via Telnet
March 30th, 2008
One of the best HTML / CSS theme songs
March 29th, 2008
Testing content_for
March 29th, 2008
After we started writing view specs we came across views similar to this:
<p>Stuff in the main content area</p>
<% content_for "secondary_content" do %>
<p>Stuff that will go in an side panel in the view </p>
<% end %>
Obviously when rendering the view inside the spec, only the blurb about main content area will be in the response.body. For instance the second spec written will fail:
describe "/path/to/view" do
def do_render
render "/path/to/view"
end
it "should have blurb about main content" do
do_render
response.should have_text(/main content/i)
end
##
# This won't pass.
##
it "should have blub about side panel" do
do_render
response.should have_text(/side panel/i)
end
end
However, you can shove something in your spec_helpers.rb to test items inside the content_for blocks.
def content_for(section)
template.send(:instance_variable_get, "@content_for_#{section}") || ""
end
And rewrite your spec like this:
describe "/path/to/view" do
def do_render
render "/path/to/view"
end
it "should have blurb about main content" do
do_render
response.should have_text(/main content/i)
end
##
# This will now pass
##
it "should have blub about side panel" do
do_render
content_for("secondary_content").should match(/side panel/i)
end
end
The have_text() matcher won't work, but you can use the have_tag().
If you haven't toyed with content_for, I suggest looking into it. It will help clean and organize your views and layout(s).
Education vs Justification
March 23rd, 2008
Aaron, Janson and I were at Applebees a month ago discussing an estimate for a client. We started talking about a particular part of the estimate that would require us to take more time than usual. We worked on their project previously, and used a few testing practices that we've stopped since. I wanted the estimate to include the refactoring of the code, but not publicize the fact. Aaron wanted to communicate with the client our exact intent.
Now keep in mind, I have no qualms about transparency with clients. And I don't go to great lengths to keep clients in the dark, as some of my previous work environments have. My point was that refactoring the code and the tests was a necessary step of development. I didn't want to publicize those specific intentions because I didn't want to come across that they were optional. In other words, I didn't want our client to think that the one of our values, quality software in this case, was negotiable.
Now, I know I may be coming across rather harshly. And I may appear as the developer with blinders, who tells everyone "Just trust me, you won't get screwed." This was exactly how I portrayed my perspective to Aaron and Janson, who more or less disagreed with me for those exact reasons. We debated for a bit longer, while eating our lunch, and I finally had the Eureka moment.
Our job is a technical one. Not only does it involve many hours of learning, but it takes the obsessive-like passion to stay current. It is rather rare for clients to possess the technical knowledge, or the experience involved in constructing quality software. However they know their domain intimately, and for a developer to play the "trust me" card in a bit arrogant. As a developer, I often forget that.
Help educate them
I was feeling as if I had to justify our development practices to the client. It made me upset that I needed to have them approve my reasoning in deciding to refactor older code. Yet as I was getting worked up, it dawned on me, the client hadn't even seen the estimate. I was already prepping counter arguments, as well as previous experiences to sell my decisions which required more work.
Listening to Aaron and Janson, I realized the client didn't need justification. They weren't bringing my decisions into the light in order to criticize my knowledge as a developer. They merely wanted to match the impact of my decisions with what they knew. They sought to understand the reasoning behind my decisions.
As I've thought more about that conversation I've come to an important resolution in my career. I should never justify myself to a client, however I should always try to educate our clients. I should spend the effort to tell them the impact of taking alternate routes. I should find better ways to articulate myself and speak their language rather than swamp them with intimidating geek-speak.
Justification isn't evil
While my client's aren't developers, I am, and so is the rest of my team. This brought up the second big question and resolution "How do I know my decision is right?", which led me to: Always justify my decisions to myself, and to my team. I believe a key ingredient in improving ourselves is constant introspection. If I make a decision, and I can't debate myself or a team member on the end result, then it's probably heavily influenced by preference, or even fear.
I should always justify to myself why we test, and the rigorousness of our tests. I should always justify why we should use agile approaches to planning. I should evaluate the reasoning behind using git over svn and whether programming in ruby makes more sense than developing in java.
I've found that it's very easy to surround yourself with a community who evangelizes tools or practices, while not sincerely asking the honest questions. I've also seen a similar pitfalls in ignoring new technologies and trends, because a lack of self-justification.
ALIVE and Treetop
February 23rd, 2008
A sweet project
I’m proud to say really fun mini-project went live today. OKWU Alive for Oklahoma Wesleyan University, a very forward thinking college. They wanted a site that is mainly updated by twitter messages.
We used a combination of Radiant, Twitter4R, and an upcoming library Treetop that I heard about a RubyConf 2007. Ever since attending Nathan Sobo’s presentation I’ve wanted to put it to use, but kept putting it off.
The “challenge”
To give some context to the site, OKWU wanted to parse direct twitter messages and add them to the site. The thing that made this interesting, is that they wanted to be able to tag each message. Most messages take on the form of:
tag : message
Now I could obviously use regular expressions to parse out both the tag and the message, but what fun is that?
Treetop to the rescue
Treetop is structured to take a grammar file, that can be brought into ruby code. Here is the grammar we used to define the twitter message:
grammar Twitter
rule status
tag delimiter message
end
rule tag
[a-zA-Z_0-9-]+
end
rule message
.*
end
rule delimiter
space* ':' space*
end
rule space
' '
end
end
If you haven’t worked with grammar specifications before, don’t feel overwhelmed. What this essentially says is “a twitter status (another definition of a message from twitter) is composed of a tag followed by a delimiter followed by a message.” With each part, you can find a more specific definition. For example, a tag can only take the form of alphanumerical characters, underscores and dashes.
“Ok, that’s neat, but how is it useful?”
The coolness comes in with the consumption of the grammar. Here’s the code that uses Treetop:
require "treetop"
Treetop.load "twitter"
parser = TwitterParser.new
parsed_results = parser.parse("awesomified : you won't believe it's that easy")
tag = parsed_results.get_tag
message = parsed_results.get_message
puts "message: #{message} classified under: #{tag}"
As you can see, Treetop loaded in the grammar and immediately gave me a TwitterParser. From there I parsed an example twitter message, and with the results I retrieved the tag and message.
“Wait, how did you get the tag and message?”
Well, I didn’t exactly show the entire grammar. Here’s the final one:
grammar Twitter
rule status
tag delimiter message {
def get_tag
tag.text_value
end
def get_message
message.text_value
end
}
end
rule tag
[a-zA-Z_0-9-]+
end
rule message
.*
end
rule delimiter
space* ':' space*
end
rule space
' '
end
end
Almost identical to the above except…it has friggin’ ruby code attached! That means when given a status, I can call #get_tag and #get_message to return the items. Pretty doggone easy.
“Impressive, but how is this better than just using regular expressions”
So I will not deny the same thing could be accomplished with a single regex, but this looks sexy. And it has additional benefits. Lets say in the future they want to:
- Allow multiple tags
- Allow spaces, and commas to be valid tag delimiters
- Allow the tags to be optional
Here’s a grammar modified with those exact requests:
grammar Twitter
rule status
(tags delimiter)? text {
def get_tags
if self.class.method_defined? "tags"
tags.get_tags
else
[]
end
end
def get_message
text.text_value
end
}
end
rule tags
tag optional_tags:(optional_tag*) {
def get_tags
[tag.get_tag] + optional_tags.elements.map { |e| e.get_tag }
end
}
end
rule optional_tag
tag_delimiter tag {
def get_tag
tag.text_value
end
}
end
rule tag
[a-zA-Z_0-9-]+ {
def get_tag
text_value
end
}
end
rule text
.*
end
rule delimiter
space* ':' space*
end
rule space
' '
end
rule tag_delimiter
space* ',' space* / space+
end
end
Some examples and their output:
results = parser.parse("tag1 : the message")
results.get_tags # => ["tag1"]
results.get_message # => "the message"
results = parser.parse("tag1 tag2, tag3 : the message")
results.get_tags # => ["tag1", "tag2", "tag3"]
results.get_message # => "the message"
results = parser.parse("the message")
results.get_tags # => []
results.get_message # => "the message"
results = parser.parse(": the message")
results.get_tags # => []
results.get_message # => ": the message"
# Yea, well not bad for only 15 min, lets chalk the last one up to user-error.
I want to thank Nathan Sobo for putting together such a useful and intuitive library. For more information about Treetop, you can check out the site as well as the mailing list.
Combined PGP Keys Into One
February 18th, 2008
After finding out today that pgp keys can have multiple email addresses, I revoked all but public key and combined all emails into one key.
How
Edit a key in the terminal:
> gpg --edit-key KEY_ID
Command> adduid
Add name and email address. Then remember to set a primary uid:
Command> uid NUMBER_IN_PARENTHS_TO_SELECT
Command> primary
Command> save
Should be all good. Remember to revoke the old keys and re-export the public key.
Additional Tip
You can share your public key with others easier by uploading it to a key server like MIT
Git Stash is Sweet
February 16th, 2008
Earlier I mentioned a method of storing away changes in a patch, rebasing and then applying the patch so you don’t have to commit beforehand.
Yesterday Janson found git-stash, and it is sweet.
- type “git stash”
- do your changes
- type “git stash apply”
- profit!

