Fancy tmux keybindings with iTerm

I wanted to bind ⌘-{ and ⌘-} to switch windows in tmux (window is to tmux as tab is to everything else). Turns out tmux won’t let you bind to ⌘. I was able to solve this with a little hack in iTerm.

In iTerm preferences, click Profiles in the toolbar, then the Keys tab. You’ll see a lieelte + button there:

Click in the “Keyboard Shortcut” field, and mash the shortcut you want to use (in my case command-shift-[).

Here is the real trick, choose “Send Hex Code” as the action.

Then in the field you want to enter the ascii code for what you want to send to tmux. In my case I used:

Key Binding Hex Code Keys Sent tmux command
⌘-{ 0x02 0x70 control-b,p previous window
⌘-} 0x02 0x6E control-b,n next window

The other thing that makes this easier to keep tmux and iterm working nicely is to use the prefix2 setting in tmux. That lets you keep control-b working as a prefix binding, but you can also use a more comfortable binding when you are typing.

# Set C-f to prefix, but leave C-b in place
set -g prefix2 C-f
bind C-f send-prefix
bind C-f last-window

I think this is a nice little trick that would work for more things than just tmux. Let me know if you find other clever uses for it.



Apache, Passenger and mod rewrite

After spending entirely too much time batteling with mod_rewrite I figured I would document how I solved my problem.

Basically I wanted different paths for my apis based on the host name. Turns out the hard part was figuring out how to convince apache to rewrite the urls so that Rails would be happy. Here is the entire apache config file (aside from the ssl and assets VirtualHosts):

# Passenger

LoadModule passenger_module /usr/local/lib/ruby/gems/1.9.1/gems/passenger-3.0.18/ext/apache2/mod_passenger.so
PassengerRoot /usr/local/lib/ruby/gems/1.9.1/gems/passenger-3.0.18
PassengerRuby /usr/local/bin/ruby_with_env

<VirtualHost *:80>
    <IfModule mod_rewrite.c>
        RewriteEngine On
        RewriteCond %{HTTP_HOST} ^api [NC]
        RewriteCond %{REQUEST_URI} !^/api [NC]
        RewriteRule ^/(.*) /api/$1 [PT,L,QSA]
    </IfModule>
    ServerName app.messageradius.com
    DocumentRoot /var/www/passenger/current/public
    <Directory   /var/www/passenger/current/public>
       AllowOverride all
       Options -MultiViews
    </Directory>
</VirtualHost>

The break down:

RewriteCond %{HTTP_HOST} ^api [NC]

This matches any domains that start with “api”

RewriteCond %{REQUEST_URI} !^/api [NC]

This will match any paths that do not start with “/api”

RewriteRule ^/(.*) /api/$1 [PT,L,QSA]

Here is the part that too me so much effort. The options passed into the RewriteRule. You need at least PT and L for Passenger to mangle the url and pass it to your app.

  • PT - Forces the resulting URI to be passed back to the URL mapping engine for processing of other URI-to-filename translators
  • L - Stop the rewriting process immediately and don’t apply any more rules.
  • QSA - Appends any query string from the original request URL to any query string created in the rewrite target.

I went ahead an added QSA to merge query parameters. I am not sure it is required, but seems to work.



localtime directive for angularjs

A little while back I wrote about a jQuery plugin I had that would convert UTC time stamps to the local timezone of the browser. Since then I have been experimenting a bit with AngularJS and wanted the same thing but in an angly way. Here is my attempt at porting that code over.

First I made a module that declared a directive:

@angular.module('localtime').directive 'localtime', ->
  # Makes a string with only two characters, adding a leading zero
  fmtZero = (str) ->
    ('0' + str).slice(-2)
  # This is the function to change if you want to customize the format of the date
  fmtDate= (d) ->
    # format the date
    hour = d.getHours()
    if hour < 12
      meridiem = "AM"
    else
      meridiem = "PM"
    hour = 12  if hour is 0
    hour = hour - 12  if hour > 12
    hour + ":" + fmtZero(d.getMinutes()) + " " + meridiem + " " + (d.getMonth()+1)+ "/" + d.getDate() + "/" + d.getFullYear()

  restrict: 'E'
  link: (scope, element, attrs) ->
    tagText = element.html()
    element.html fmtDate(new Date(tagText))
    element.attr "title", tagText

The real magic is in the link function that grabs the current html content for the element and overwrites it. To help with debugging I stick the original timestamp in the title attribute – which you can see when you mouse over a date.

Then in my angular app, I just include the module:

@myApp = angular.module('myApp', ['localtime'])

Now, in my markup I simply wrap the timestamps I care about in <localtime> tags and they get switched over to a nicely formatted string in the user’s local time zone.

The end result is a timestamp string going from this:

2013-02-26T17:53:00+00:00

To this:

12:53 PM 2/26/2013



Vim - highlight debugger statements

I know some folks thoroughly disapprove of using debugger, but in the context of a big app, using a framework or libraries you didn’t write I find them crazy helpful. Plus you can drop into your unit tests to track down a failure so easy.

My problem is I have been known to check in code that has a debugger statement. Only to end up with a git log like this:

* 0f93265 Remove debugging statements.

I used a git pre-commit hook for a while to stop me from checking bad things in, and that did the job but I found it to be jarring. Really what I needed was to make it painfully obvious when I had dropped one into my code. This gets the job done nicely in vim:

" Make those debugger statements painfully obvious
au BufEnter *.rb syn match error contained "\<binding.pry\>"
au BufEnter *.rb syn match error contained "\<debugger\>"

Also in a gist.



Source Maps with Chrome Canary and Rails

I was having problem piecing together all the steps to enabling source maps in Chrome Canary. I really wanted to get it working with the rails-sass gem that comes with Rails 3, and the Asset Pipeline.

Eventually I got things working, this is what I did:

Step 1:

In Chrome Canary navigate to chrome://flags/

Step 2:

Search for “Developer Tools experiments” and enable

Step 3:

Enable sass support in the developer tools:

  1. View->Developer->Developer Tools.
  2. Click the gear in the bottom right.
  3. Choose the Experimental Tab.

Settings:

Experiments tab:

Step 4:

In config/enviroments/development.rb Add config.sass.debug_info = true inside the Application.configure block.

MyApp::Application.configure do
  # Settings specified here will take precedence over those in config/application.rb

  # ...

  # Do not compress assets
  config.assets.compress = false

  # Expands the lines which load the assets
  config.assets.debug = true

  # Enable source maps in the browser
  config.sass.debug_info = true
end

This should cause rails-sass to include the @media -sass-debug-info statements in your generated application.css file. I found it helpful to visit /assets/application.css directly on the rails app to make sure that was working.

Step 5:

Reboot all the things. Reload rails server. Reload the browser.

Step 6:

Now the developer tools links to your sass files directly. Huzzah!