Here’s a fun bit of JavaScript inspired by Yehuda Katz’s jspec. It lets you call a function with a particular scope, making it ideal for calling functions that depend on a particular scope, but for whatever reason you don’t want to set up that scope statically.

function callWithScope(fn, context, scope) {
  var fn_body = fn.toString().match(/^[^\{]*\{((.*\n*)*)\}/m)[1];
  fn = new Function('__scope__', 'with(__scope__){\n' + fn_body + '\n}');
  return fn.call(context, scope);
}

How might this be used? When writing a JavaScript spec, allowing the describe callback function to call it.

describe("callWithScope", function() {
  it("should not retain the original function scope", function() {
    ...
  })
})

Notice that it doesn’t appear to come from anywhere. When the callback passed to describe is given to callWithScope, the call might look something like this:

callWithScope(callback, this, {it: function(name, body) { ... }})

The describe callback function is turned into a string and turned into a new function of one argument, the scope. It makes it look something like this, though this isn’t entirely accurate:

describe("callWithScope", function(__scope__) {
  with(__scope__) {
    it("should not retain the original function scope", function() {
      ...
    })
  }
})

I’m using this in one project to call functions defined in some external scripts that expect certain objects and functions to be available. Also, since I can pass in my custom scope, I don’t have to do the work of ensuring that every function that needs that scope is declared within it. This allows me to abstract out a lot of shared code.

I’m sure there are a lot of uses for this I haven’t thought of. What’s yours?

I’ve started using Git as my SCM of choice for Subversion projects over the last several months and have found that, while I don’t want to use Subversion anymore, there are some things it makes easier than git. For example, let’s say you’re working on something and you want to pull in the changes from other people on your team. With svn it’s simply:

$ svn up

With git things are different, since it only merges changesets and not locally changed files. This was a pain before git-stash came along, since I’d have to back out a change, update, and then reapply it. Even with git-stash things are a bit more painful. Here’s the equivalent to the above for a git-svn project:

$ git stash
$ git svn rebase
$ git stash apply

Oh, and that’s only if you’re on the master branch. If you’re on another one (and you should be), then here’s what it looks like if you want to keep master up to date too:

$ git stash
$ git checkout master
$ git svn rebase
$ git checkout mybranch
$ git rebase master
$ git stash apply

Whew! Note that this mostly applies to git-svn projects. For regular git projects a git-pull will do nicely.

I got sick of this, and I noticed that the Rubinius project uses a Rakefile to handle a fair number of the git commands, including updating and pushing. Here’s a Sake script that gives you two tasks: git:update and git:push which automatically check whether the project is a git-svn project and do the right thing. Install it like so:

$ sake -i http://pastie.caboo.se/147964.txt

And now we’re back to a one-liner:

$ sake git:update

Update: I just added git:open and git:close which you should think of as opening and closing issues. They just create and delete branches and can be used like this:

$ sake git:open
* Name your branch: ofx
* Switching to master
Switched to branch "master"
Switched to a new branch "ofx"
$ sake git:close
* Switching to master
* Deleting branch ofx

And don’t worry, git:close is safe and won’t destroy your work if you haven’t merged it yet:

$ sake git:close
* Switching to master
* Deleting branch ofx
* Branch ofx isn't a strict subset of master, quitting

Update: I gave this its own repo on github, so go forth, and git.

Git is split up into a whole bunch of executables like git-commit and git-status, but you can also run them by doing git commit and git status. Cool, right? But it doesn’t work with your own scripts, so you can’t just put git-wip in your PATH and have it work. To fill this need I cooked up a Zsh function that does what git should be doing itself:

    git() {
      for p in $(echo $PATH | tr ':' '\n'); do
        if [[ -x "$p/git-$1" ]]; then
          eval "$p/git-$1 $argv[2,-1]" && return
        fi
      done

      eval "/usr/bin/env git $argv"
    }

Update: The above function has the annoying side-effect that if the git command fails or any valid reasons (such as canceling a commit by not providing any message), it’ll try to run it again. For that reason, and since Coda showed me how to shell out with git aliases, I recommend not using this function.

Now that I’ve had Leopard for a while I think I’ve settled the dispute between Time Machine and File Vault. Time Machine won out.

The problem was that FileVault works by setting up an encrypted disk image that is mounted in the /Users directory, rather than /Volumes where things you mount yourself (like DMGs) go. This allows you to pretty much transparently interact with your files, blissfully unaware that they’re being encrypted/decrypted on the fly, however to Time Machine your whole home folder is just one file. So while I’ve heard something about being able to access stuff by digging around in the bowels of the directory structure that Time Machine sets up on the external hard drive, you can’t use Finder’s interactive file restore system, making it much less useful IMO. After all, backup is an old problem that has solutions, but the whole point of Time Machine is to make it easy enough to actually use.

So my solution was to instead put everything that I wanted encrypted into an actual encrypted disk image that I just mount myself. This also had the benefit of slightly speeding up my system, especially login.

I upgraded to Leopard over the weekend after borrowing a friend’s copy, since I just couldn’t wait for mine to arrive (thanks Coda!), and it’s been overall a Good Thing. Leopard has brought us new versions of just about every app in OS X. The most notable ones, for me, are Mail, iCal, Terminal, Spaces, and Stacks.

Mail.app

Mail got an iTunes-like sidebar and a little Mail Activity status area (yes, there are other things like Notes and Todos, but I haven’t bothered to use them yet). The update coincided with GMail’s addition of IMAP, a long-awaited feature — especially for us iPhone users. My previous solution of forwarding all my accounts to a fastmail.fm account is pretty much defunct. Setting up GMail’s IMAP on two accounts with a combined message count of 17,904 was not a fun experience. Now that I’ve set it up and tweaked a few things it seems to be humming along quite nicely, Inbox Zero style. Here’s what I recommend you do if you’re going to set up IMAP with GMail:

  1. Log into gmail.com
  2. Archive everything (except stuff you haven’t dealt with yet)
  3. Delete all your labels (maybe, see below for an explanation)
  4. Enable IMAP under Settings
  5. Add the GMail account to Mail.app (I’ll call it “Personal”)
  6. On the sidebar in Mail select Personal → [Gmail] → Sent Mail, then choose the Mailbox → Use This Mailbox For → Sent
  7. Do the same for Trash, Junk, and Drafts
  8. Install Mail Act-On (might require some Terminal tweaking)
  9. Create an archive rule called “Act-On: y | Archive” and say that if it’s in “Personal” to move the message to Personal → [Gmail] → All Mail
  10. Repeat #9 for each other account you have

Now you’ll have the ability to get to that holy grail of email, Inbox Zero, with more ease than before. Under this setup you’ll have an inbox, but it’ll be empty most of the time. The email you’ve dealt with will be archived and will be visible in Mail under Personal → [Gmail] → All Mail and under All Mail on gmail.com. Oh, and about step #3.. when GMail first came out and told us “search, don’t sort” and gave us labels I thought I understood what to do, but what I ended up doing was pretty much sorting email into labels, going totally against how GMail is set up. What I discovered is that labels should only be for emails that you still have an active interest in, otherwise you’re just sorting and filing. In GTD-speak that’s only use labels for emails that still have an action associated with them. By the way, this applies locally to Mail.app as well. Get rid of your folders. You only need Smart Mailboxes and search. Try it, you’ll like it.

iCal

The only thing that looks the same (almost) in this version of iCal is the events view. Everything else has been tweaked. The mini-calendar is more legible and larger. The list of calendars has, like Mail, been iTunes-ified. The biggest change is the dropping of the edit drawer in favor of a popup. My only complaint with it is that I don’t understand why they went with a drop shadow under the text boxes inside rather than a fuzzy blue border like in Safari.

Terminal

So Terminal has real preferences now, and tabs. The former is nice, but I’ve already set things up so I doubt it’ll have much effect. The latter has been mitigated by the fact that I use screen. Oh well, they’re welcome additions anyway. Thanks Apple!

Spaces

This is probably the best new feature in Leopard as far as I’m concerned. Don’t get me wrong, I’m excited about Time Machine, but mostly because it’ll encourage other people to back up more, making the Mac ecosystem a better place to be. Most of the other things in Leopard are not really big-ticket items, but are nevertheless cool to have. I’m still noticing little things, like the fact that ⌘⇧4 (grab selection) now has coordinates and dimension numbers — nice touch!

Anyway, Spaces is exactly what Virtue Desktops and Desktop Manager should have been. The animation is exactly right (windows slide off the screen in the direction of motion, the pager comes onto the screen with the arrow inside the old space pointing to the new one), windows that live on all spaces are supported and predictably stay put when switching spaces. Dragging apps around when viewing all spaces is dead simple, and Exposé even works in that view. All-in-all, I’m very impressed with their implementation of virtual desktops.

Stacks

I’ve only got the default stacks in my dock right now (Downloads and Documents), but I’m digging this feature already — enough to make me leave the Dock visible and put it on the left side. So now the Dock does have a use for me: My Active Stuff. I removed all apps from it, so only running ones show up. I can easily click on the stacks in the dock, pull out the thing I want to mess with, and either open it or drag it to an application (usually opening folders in TextMate).

Ruby

Despite the best laid plans of mice and men, Ruby is still broken under Leopard. Not as broken as Tiger, mind you, but broken is broken. So I’m sticking with my Tiger setup of using MacPorts for everything. Oh well.

3rd-Party Apps

  • Spanning Sync went bonkers and now wants to delete all my iCal events. sigh
  • 1Password refused to work at first, but has been updated for Leopard and now works just as before
  • Pyro and Safari 3 are feuding, and as a result you can’t upload files in Pyro

So all in all I’m quite pleased with the upgrade, and I recommend you check out the Ars Technica review for more. It has already changed the way I work for the better, though how much of that is coincident I’m not sure yet.

Firstly, one feature that Mobile Safari on the iPhone has is the ability to double-tap a portion of the page to have that take up the whole screen. This is really great for reading articles on blogs and other news sites, and I thought that it would be a great addition to Safari (or any other browser) since it allows you to focus on just that part of the page you want, ignoring the ads etc.

Second, it’s stupid that I can’t view the picture for a contact in full screen unless they’re calling me or I’m editing the picture. I should be able to tap on the photo when viewing the contact to see it full screen.

I’ve been away for the last 10 days or so on a well-deserved vacation. Here are a few updates that all have to do with money:

  1. The Fed lowered the Prime Rate, and ING Direct lowered their interests rates the next day
  2. Helio finally gave me the $272 they owed me (which after 9 months they should owe me $10 interest, but whatever)
  3. I now work for wesabe.com, a personal finance website
  4. I’m switching to EverBank from ING’s Orange Savings and Wells Fargo’s checking

I’m really excited about the new job, in part because I think it’s a cool company with a good product, but also because I’ll still get to do Rails work with some pretty cool people, like Coda Hale and Andre Arko. Attendio was a good learning experience for me, and I wish them luck in the future, but I think it was time for me to move on and I think I made the right decision.

Number 1 doesn’t bother me so much because of number 4, as EverBank has yet to lower their rates (which stand at 5.01% APY vs. ING’s 4.20% APY for Money Market and 3.65% APY vs. WellsFargo’s 0.00% APY on checking). EverBank also lets you send electronic (or paper) checks, though you can’t write them yourself — you do it online — and you get an ATM card which you can use at BofA, Wells Fargo, and more and they will reimburse you up to $6/mo in fees from other banks, which I estimate to be about two withdraws per month — more than I ever make.

The Helio thing came four days after my last conversation with them (9/17 to 9/21), indicating that perhaps the only way to get your refund back is to be a persistent and bitchy thorn in their side. I’m glad that chapter in my life is closed.

I finally found, after about two months, a couple things I want the iPhone to do that it doesn’t do:

  1. Upload to Flickr
  2. Play music over an Airport Express

The first may be taken care of with a third-party app, like Pushr or iFlickr. The latter is a bit more tricky, or at least would be if we wanted it done right (as part of the iPod app — hint, hint Apple). But hey, give me a simple interface to browse songs and I’d be satisfied for a first attempt.

Having recently dealt with Apple in buying the iPhone and having to continually deal with Helio to give me my money back, I thought I’d compare and contrast the experiences I’ve had with them.

Helio hasn’t refunded the money they owe me when I’ve been asking for it for the last nine months. Apple gave me back $100 that they didn’t even owe me, and the refund took about two minutes.

Helio’s customer service representatives are either dumb, misinformed, or powerless to help when confronted with a problem. Apple’s customer service representatives are knowledgeable, intelligent, and generally do the right thing (such as when they completely overhauled my old PowerBook when I sent it in for the final repair).

Helio and Apple both try to appeal to the hip and young crowd, but Helio does it with slogans and cute phrases over the phone, such as “How can we make your day better?” and “If you’re holding [on the phone], you must not be happy.” Apple does it with superior design, superior service, and simplicity.

I spent about an hour on the phone today with Helio, today being about a day later than they said I should have my refund. Since I last blogged about it they pushed it off in August, saying that the approval process should take no more than two weeks from that date, pushed it off again at the end of August, and now pushed it off again in mid-September. Not only that, but they’re now saying 59 business days, not just days. The last person I spoke to said that I could expect the refund 59 business days from today. This is simply amazing. This company has so much contempt for their customers, it is unbelievable. They now tell me that I should wait until December 10th to receive the refund, or over a whole year since I cancelled my account.

While cell phone carriers may suck in general, Helio raises the bar on horrible so much that it’s hard to compete with without going out of business (which I predict Helio will do within a year). Anyone interested in getting a class-action suit together?

I was a little disappointed by Apple’s decreasing the price of the iPhone by $200 so shortly after it came out. That’s 33% off, quite a big discount and, for some early iPhone adopters, a slap in the face. I felt like this: I was willing to pay for it at the full price, and I did — lowering the price doesn’t invalidate my decision. And so I was prepared to continue to enthusiastically support Apple, but maybe adding the caveat that you really ought to do your homework before you buy, and even then you might get screwed.

But not now. Apple has decided to give every iPhone owner $100 back. Apple rocks and I’m glad they chose to do right by their early adopters. Thanks guys.

Next Page »