Changing Folders in Mutt Can Be Faster

For a while, I have found that changing folders in Mutt was artificially slow. At least it seemed artificial. If my Inbox has, say, 50 messages, and some other folder has 10, why does it take over a second to switch between the two? There can’t really be *that* much processing to do.

I use Mutt because it is fast, overall, but over a second to change between small folders is too long. Turns out that delay was indeed artificial as I had suspected. The fix is simple, put this in your ~/.muttrc:

1
set sleep_time=0

The default is 1 second.

The official story behind this setting is it “[specifies] time, in seconds, to pause while displaying certain informational messages, while moving from folder to folder and after expunging messages from the current folder. The default is to pause one second, so a value of zero for this option suppresses the pause.”

Thanks to a kind soul in #mutt for pointing this out to me.

Off to RubyConf…

Will be on a plane today traveling to Charlotte, NC for RubyConf ‘07! Mark Daggett and I will be meeting up (for the first face-to-face in almost a year), drink some beers, and maybe do a little codin’ on Pledgie.

Anyone want to meet up? I know a few of you out there, but others I know only by IRC handles, voices in a screencast, or your blog posts. I look like this:

Leave a comment, we’ll grab some beers, or just say Hi if you see me :)

Vimperator Stunned

I have long been a user of the Conkeror plugin for Firefox, which allows keyboard driven browsing (no mouse needed). Just yesterday I tried the Vimperator plugin, which is similar but has much better vi-like keybindings (hence its name). Perhaps I’ll write more about the plugin itself later, this post is just about a problem I had, and how to fix it.

I put the following line in my ~/.vimperatorrc:

1
:set showtabline=0
and next time I started Firefox, Vimperator was dead. Stunned, completely dead. Even if I took that line out, Vimperator still wouldn’t work. Firebug reported:
1
vimperator.commandline has no properties

I was bummed, didn’t know how to revive it. I uninstalled it, reinstalled it, even deleted Firefox! No go.

Finally, I see there is this “prefs.js” in my Firefox profile directory that has a reference to “showtabline”. Taking the hint at the top of that file, I visited “about:config”, searched for “vimperator”, right-clicked on the “showtabline” property, and hit “Reset”. Restarted Firefox and Vimperator was resurrected!

I was quite jazzed.

Minimal Footprint SSH Agent Forwarding on OS X

Those who know me know that I’m a minimalist. I don’t like more than is needed to get the job done. I don’t like “tools” and applications that slow me down. For example, I read my email in mutt, a text-based email client, because 99% of my email is text. My hands stay on the keyboard because a mouse is not needed. Coincidentally, that’s also where my hands need to be to type an email. Is this beginning to make sense?

In this light, I run the SSH authentication agent known as, uhhh.., ssh-agent. The one that comes with SSH. No frills, nothing extra to download. I’m going to show you a copy & paste setup of ssh-agent that will make forwarding of your authentication details worry free and bloat free.

Let me first give a brief intro to SSH agent forwarding and then dive into the details.

When you SSH to a server from your laptop, and you authenticate via your key, life is good… until you want to SSH to another server, from the first server. Your private key doesn’t exist on the first server (as it definitely should not), so you can’t use it to authenticate. To solve this problem, you want the key on your laptop to “follow” you around from box to box. This is done with SSH agent forwarding.

This feature of SSH is disabled by default, there is a security risk; the man page tells us:

1
2
3
4
5
6
7
Agent forwarding should be enabled with caution.  Users with the
ability to bypass file permissions on the remote host (for the
agent's Unix-domain socket) can access the local agent through
the forwarded connection.  An attacker cannot obtain key material
from the agent, however they can perform operations on the keys
that enable them to authenticate using the identities loaded into
the agent.

Bah, I don’t really care.

Turning on SSH agent forwarding is two simple steps. First, put the following in your ~/.bash_profile:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
SSH_ENV=$HOME/.ssh/environment

function start_agent {
     echo "Initializing new SSH agent..."
     /usr/bin/ssh-agent | sed 's/^echo/#echo/' > ${SSH_ENV}
     echo succeeded
     chmod 600 ${SSH_ENV}
     . ${SSH_ENV} > /dev/null
     /usr/bin/ssh-add;
}

# Source SSH settings, if applicable

if [ -f "${SSH_ENV}" ]; then
     . ${SSH_ENV} > /dev/null
     ps -x | grep "^ *${SSH_AGENT_PID}" | grep ssh-agent$ > /dev/null || {
         start_agent;
     }
else
     start_agent;
fi

Next, add this to your ~/.ssh/config:

1
ForwardAgent yes

That’s it, just copy & paste.

I am, however, assuming you are running bash as your shell (the default on OS X). To my zsh friends, someone will have to translate. Also note, this isn’t limited to OS X, I do believe the bash code is generic enough to put on any Linux, FreeBSD, etc… box. You might have to change the args to “ps” is all.

The first time you open up your terminal you will see ssh-agent starting and loading up your key(s). If you have set a passphrase on your key (you better!), you will be prompted for it once, and ssh-agent will remember it, until you kill it or turn off your laptop. Additionally, it’ll forward your credentials as you hop from server to server, so you may authenticate w/o having your private key on each server. Once again, this behavior will persist unless you explicitly kill ssh-agent, so it’s maintenance free.

Life is good.

Params[:user] && Params[:user][:name], Can We Make It Shorter?

Was talking with evan (Evan Phoenix) and hasmanyjosh (Josh Susser) in #caboose at too late of an hour, and came up with some code that may or may not be useful.

I frequently see code like this in Rails apps:

1
@name = params[:user] && params[:user][:name]
(actually Josh came up with that example)

Can’t just do “@name = params[:user][:name]” because params[:user] might be nil. Of course, we should be checking for nil values at some point earlier in the game, but nevertheless, this pattern seems common enough, so let’s see if we can do something fun with it.

If params[:user] is nil, we will get a too familiar exception:

1
2
3
4
>> @name = params[:user][:name]
NoMethodError: undefined method `[]' for nil:NilClass
        from (irb):2
>>

What happens if we define a method ‘[]’ on NilClass and have it return nil? Conceptually, doesn’t seem to hurt this case. In other cases, I’m not sure, I’ve only had it in my head for about 10 minutes.

1
2
3
4
5
class NilClass
  def [](*args)
    nil
  end
end

Now, using the same example above, we don’t get an exception:

1
2
3
>> @name = params[:user][:name]
=> nil
>>

In fact, we get the same result had we split the hash lookups with &&.

Useful? Scary? Not a good idea? Comments are welcome.

Cheat and Git

If you don’t already have the Cheat gem, don’t wait any longer to type:

1
gem install cheat -y
Then on the shell you can get quick cheat sheets for a plethora of tools:
1
2
3
4
cheat rspec
cheat mate
cheat strftime
...

This short article is just to announce that I’ve updated the Git cheat sheet heavily tonight. You can view it online here or just type:

1
cheat git
Remember to add “–new” at the end if you already have a cached copy.

If mistakes are found (and I’m sure there are a few), please view the web version, click “edit”, and correct it. Thanks!

Vlad the Deployer and Git

Update (02-03-2008): As of Vlad 1.2.0, this module is included. You will have native Git support.

So you want to use Vlad the Deployer to deploy your apps. You’ve found its simplicity elegant. You’ve seen the light when it comes to distributed vs. centralized version control systems and decided distributed is the only way to go. You’ve sat down to write your deployment recipe, only to find, to your horror…

…only Subversion and Perforce are supported.

No longer. I present to you a Git module. Just a sidenote, in light of accuracy, Mercurial support is in the development version, and darcs support is in a patch on RubyForge.

Now, with this module I also provide a small patch to lib/vlad/core.rb. At the time of this writing, Vlad 1.1.0 is the latest version and does not have all that is needed to support the pile of awesome that Git provides. Specifically, it hard codes “head” as the revision in every checkout. That’s no good with Git, because we may want to deploy a branch, tag, or arbitrary SHA1 commit ID.

Enough of that, let’s have some fun. Install the module and my patch to core.rb like so:

1
2
3
cd $GEMPATH/vlad-1.1.0
wget http://scie.nti.st/dist/git-vlad.diff
patch -p1 < git-vlad.diff

Replace $GEMPATH with the real path to your Gems.

Now, in your Rakefile, you will want the couple lines that refer to Vlad to look like this:

1
2
require 'vlad'
Vlad.load :scm => :git

I can’t seem to override the scm in config/deploy.rb, even though Vlad implies you can do so. Perhaps a bug, no matter. Here’s a simple 3-line deploy file (config/deploy.rb):

1
2
3
set :domain, "myhost.com"
set :deploy_to, "/var/www/"
set :repository, "dev1.myhost.com:/var/git/repo.git"

Now you can proceed to deploy as usual (rake vlad:update && rake vlad:migrate && rake vlad:start).

There is another variable you can put in config/deploy.rb which is called “revision”. Here are a few examples:

1
2
3
4
5
6
7
8
# Deploy the latest code, this the default
set :revision, "HEAD"

# Deploy branch "origin/my_branch"
set :revision, "origin/my_branch"

# Deploy tag "1.0"
set :revision, "1.0"

That’s about all there is to it. Questions, comments, bugs, mistakes, praises, boos? Please leave a comment.

Capistrano 2.0, What Happened to My Mongrel Recipes?

Did you upgrade to Capistrano 2.0 only to find your Mongrel cluster recipes aren’t working?

Bleh… same here.

Turns out you need to namespace your Mongrel cluster recipes to “deploy”.

Apply this patch and you should be good to go:

1
2
3
cd $GEMPATH/mongrel_cluster-0.2.1/lib/mongrel_cluster/
wget http://scie.nti.st/dist/mongrel_cluster_recipes.rb.diff
patch -p0 < mongrel_cluster_recipes.rb.diff
Change path as needed.

Here’s the patch for reference:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
--- recipes.rb.orig     2007-09-03 17:37:28.000000000 -0700
+++ recipes.rb  2007-09-03 17:37:48.000000000 -0700
@@ -1,3 +1,6 @@
+# This is the stock mongrel_cluster/recipes files except adapted for
+# Capistrano 2.0.  We must namespace each task to "deploy".
+
 Capistrano.configuration(:must_exist).load do
   set :mongrel_servers, 2
   set :mongrel_port, 8000
@@ -8,6 +11,8 @@
   set :mongrel_group, nil
   set :mongrel_prefix, nil

+  namespace :deploy do
+
   desc <<-DESC
   Configure Mongrel processes on the app server. This uses the :use_sudo
   variable to determine whether to use sudo or not. By default, :use_sudo is
@@ -72,9 +77,11 @@
   task :spinner, :roles => :app do
     start_mongrel_cluster
   end
+
+  end

   def set_mongrel_conf
     set :mongrel_conf, "/etc/mongrel_cluster/#{application}.yml" unless mongrel_conf
   end

-end
\ No newline at end of file
+end