Archive for the “Programming” Category

My last iPhone contract app, ExecTweets for iPhone, is now on the App Store. This is the project that drove the creation of FeedParser (an open source Obj-C RSS parser). Anyway, it’s free, and if you like reading about business advice from top business execs, check it out!

Comments Comments Off on ExecTweets on the App Store

Update: I've refactored the code significantly and introduced the ability to explicitly unguard methods from within specs.

One problem I find myself having when writing tests is ensuring that no execution ever leaves my little test sandbox. For example, when writing tests for github-gem I keep looking through the code to find every place a function ends up `shelling out` and it's tiresome and error-prone. I finally decided I was going about this backwards. Testing is supposed to find problems for me, right? So why not raise an error whenever `` or Kernel#system() is called and let the tests tell me what else I need to mock?

Put the following code in your spec_helper.rb file and an exception will be raised whenever `` or Kernel#system() is called during a test:

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class Module
  def metaclass
    class << self;self;end
  end
end
 
module Spec::Example::ExampleGroupSubclassMethods
  def add_guard(klass, name, is_class = false)
    guarded = nil # define variable now for scoping
    target = (is_class ? klass.metaclass : klass)
    sep = (is_class ? "." : "#")
    target.class_eval do
      guarded = instance_method(name)
      define_method name do |*args|
        raise "Testing guards violated: Cannot call #{klass}#{sep}#{name}"
      end
    end
    @guards ||= []
    @guards << [klass, name, is_class, guarded]
  end
 
  def add_class_guard(klass, name)
    add_guard(klass, name, true)
  end
 
  def unguard(klass, name, is_class = false)
    row = @guards.find { |(k,n,i)| k == klass and n == name and i == is_class }
    raise "#{klass}#{is_class ? '.' : '#'}#{name} is not guarded" if row.nil?
    (is_class ? klass.metaclass : klass).class_eval do
      define_method name, row.last
    end
    @guards.delete row
  end
 
  def class_unguard(klass, name)
    unguard(klass, name, true)
  end
 
  def unguard_all
    @guards ||= []
    @guards.each do |klass, name, is_class, guarded|
      (is_class ? klass.metaclass : klass).class_eval do
        define_method name, guarded
      end
    end
    @guards.clear
  end
end
 
Spec::Runner.configure do |configuration|
  configuration.prepend_before(:all) do
    self.class.send :include, Spec::Example::ExampleGroupSubclassMethods
  end
 
  configuration.prepend_before(:each) do
    add_guard Kernel, :'`'
    add_guard Kernel, :system
    add_class_guard Process, :fork
    add_class_guard Open3, :popen3 if defined? Open3
  end
 
  configuration.append_after(:each) do
    unguard_all
  end
end

Note: if you want, you can write :` instead of :'`', but my syntax highlighter here doesn't like that.

Comments Comments Off on Guarding against `โ€Œ` and Kernel#system() in your tests

Recently I was contracted to write some software, and it’s just now been released. It’s called GrabUp. Basically, the whole purpose here is for zero-click sharing of screenshots. GrabUp is a daemon that sits in the background and waits for you to take a screenshot, then it instantly uploads it to the GrabUp servers and puts the URL on your clipboard. It has a nice status item to let you know when it’s done. If you have GrabUp running and you want to share an image, just take the screenshot and then paste the URL anywhere. So far, GrabUp has been seen in TUAW and we also got a rather nice blog post reviewing it.

Comments 3 Comments »

I’ve just pushed a new version of SafariSource out the door which is once again compatible with Safari Tidy. Please let me know if you have any problems. You can download it here.

Note that this requires version 0.2.5 of Safari Tidy, which was just released today.

Comments Comments Off on SafariSource v1.7.4 compatible with Safari Tidy

For those interested, I am currently maintaining git mirrors of the MacPorts and TextMate Bundles svn repositories on GitHub. I update these periodically, but at the moment only the master branch is published.

Comments 1 Comment »

I just released a new version of SafariSource which supports Safari 3.0 last night. This morning I received a Czech localization from Jakub Formanek, so I just released SafariSource v1.7.1. with the new localization.

So if you’re using Safari 3.0, or if you’re Czech, go ahead and download SafariSource. If you’re using Safari 2.x, please let me know it still works as I can’t test that with 3.0 installed.

Comments Comments Off on SafariSource update

tcltumblr 0.1 is available for immediate use. It is a Tcl library that provides access to the Tumblr API.

Download

Comments Comments Off on tcltumblr 0.1

After months of absence, Typosphere has returned from the dead!

We migrated off of Planet Argon and onto DreamHost, where we should have more control. We also upgraded to Trac 0.10.3 and turned off anonymous editing (users now have to register to file a ticket). This should (hopefully) prevent the issue that lead to Typosphere dying in the first place.

One important thing to note is that as part of this process, we also moved the subversion repository. Unfortunately, the old repository was hosted as an svn:// URI using the typosphere.org domain, which meant there was no way to preserve this URI (since we can’t run long-lived background daemons on DreamHost). The new URI uses http and a new subdomain, so if necessary we can move the repository without moving the website.

The new repository URL is http://svn.typosphere.org/typo/trunk.

Read the rest of this entry »

Comments 3 Comments »

Haml is a new markup format for Ruby on Rails apps that just hit 1.0. At first glance it looks pretty odd, but it turns out to be really easy to write in, and it’s shorter and, actually, easier to read than the equivalent eRB.

I think I’m going to convert Typo to use Haml for all its templates. I already did Azure’s layout file and it was pretty simple.

Comments 2 Comments »

Update: This code was written pre-Leopard, and as such doesn’t run under ObjC 2. See JRSwizzle for an updated version that runs under Leopard and Snow Leopard.

Method Swizzling is one common technique of people writing hacks, such as Safari Plugins. Unfortunately, it’s always suffered from a flaw, wherein swizzling inherited methods affects all classes which inherit that method (including the base class), rather than the intended subclass. This problem is discussed on the CocoaDev Method Swizzling page.

As part of writing YubNubSearch, I decided to solve this problem.

First I looked into dynamic subclass generation + posing. Unfortunately, this has a big problem. In this technique, calling the original implementation would naturally be done through a [super foo] call. Unfortunately, when the compiler sees super, it hardcodes a reference to the superclass at which to start the search. This means you cannot write this code in, say, a category on NSObject, then pull up the IMP into a dynamically-generated subclass and have it work. So that throws out that idea.

The other idea I had, which I eventually went with, was to copy inherited methods into the subclass that you wish to swizzle, before swizzling. It turned out to be fairly easy, and still has the same semantics as the old, flawed technique for calling the original implementation.

You can download my implementation here.

Comments 6 Comments »