[Skip To Content]


# The One Thing I Like About PHP

  1. <?
  2. class B {
  3. function hello() {
  4. echo "HAI\n";
  5. }
  6. }
  7. $a = "hello";
  8. B::$a();
  9. ?>

# Ruby Games Programming

Gosu is a 2D game development library for the Ruby and C++ programming languages, available for Mac OS X, Windows and Linux.

  1. require 'rubygems'
  2. require 'gosu'
  3. class MyWindow < Gosu::Window
  4. def initialize
  5. super(640, 480, false, 20)
  6. self.caption = 'Hello World!'
  7. end
  8. end
  9. w = MyWindow.new
  10. w.show

I can’t wait to find the patience to do something cool with this.

# Editing TextMate's Syntax Highlighting

I generally use TextMate for text editing these days, so I’ve slowly being building up a bunch of custom modifications to the stock install. The most obvious of these modifications is changing the colours of the syntax highlighting, which matches the code snippets you see on this blog.

If you use TextMate yourself, you’ll know that it supports highlighting multi-line comments differently from single-line comments, but if you’re a Ruby coder, you’ll know that the only kind of multi-line comments it supports is the nasty =begin/=end thing which can’t have any whitespace preceding them and thus messes up your nicely indented code :

  1. module Supermodel
  2. =begin
  3. This class encapsulates all information about a given index.
  4. Blah blah blah.
  5. Blah.
  6. =end
  7. class Index
  8. def initialize()
  9. # Do stuff
  10. do_stuff
  11. end
  12. end
  13. end

Ugly.

What I ideally want is some way of using the same multi-line highlighting (with the dark grey background) but without having to use =begin and =end, and without having to bind everything to the beginning of a line.

And that’s now what I have, this is a screen grab from TextMate (I’ve not got round to mirroring the changes on the blog yet) :

You’ll notice I’m using ## to mark a line which should be highlighted in that manner, separately from a normal comment beginning with #.

And here’s how I did it!

TextMate’s syntax highlighting turns out to be pretty fantastic and flexible. You can read about it here and here and here, and probably on some other pages on that site too.

The first step is to define a rule for the new highlighting type. From within TextMate, if you go to the Bundles → Bundle Editor → Show Languages menu option, you’ll get a list of languages that TextMate will highlight for. Open the Ruby node in the tree-view, and you’ll see one language – Unsurprisingly, called ‘Ruby’. I copied this, creating a new language called ‘Ruby (double-number-sign highlight)’.

Having read the above about scoping, I changed the scopeName at the top of the new language definition to source.ruby.double-number-sign-highlight to avoid any crazy clashes that might occur otherwise. This might be unnecessary, but it seems correct.

If you then search the language file for comment.line, you’ll get to the place where we need to add our new rule. Here’s the new rule we’re going to add :

  1. { name = 'comment.line.double-number-sign.ruby';
  2. match = '(?:^[ \t]+)?(##).*$\n?';
  3. captures = { 1 = { name = 'punctuation.definition.comment.ruby'; }; };
  4. },

You can see it’s very similar to the existing comment.line rule. Make sure you add that rule above the existing one, the rules seem to be traversed in order until one matches, and obviously a rule looking for a line beginning with # will match one beginning with ##.

Now that we have the new rule set up, we just need to tell TextMate how to use it. Close the Languages window, and then go to TextMate → Preferences → Fonts & Colors. You’ll see the usual colours you use for your highlighting. To add a new highlighter, click the + button, and a new rule will appear. Set its name to something like ## comment, and set the colours you want to use. Then, importantly, change the Scope Selector entry to read comment.line.double-number-sign (Note that although the field in a drop-down menu, you can type new entries into it too.)

And that’s it! If you open up some existing Ruby code, or create a new file, and ensure that you use the Ruby (double-number-sign highlighting) language (You can set that using one of the menus at the bottom of the TextMate window), any comments you create with ## will be highlighted differently to #.

If you don’t want to go through all the hassle of setting this up yourself, you can download a disk image containing the new language and a theme that highlights the double-hash-sign below :

To install them, just double-click on the files once you’ve mounted the .dmg. They’ll be copied by TextMate to ~/Library/Application Support/TextMate, from where you can delete them if you want.

# Siggy Stardust

If you’ve ever been frustrated by the lack of control that most mail clients give you over your signatures, then Siggy Stardust is for you. It’s basically an SMTP proxy, which simply adds signatures to the end of any mails you send according to rules that you set up. The rules are written in pure Ruby, and so you can do pretty much anything you want within them.

For example, here is my current rules file at Teh Office. If all the recipients of a mail are within 29degrees, then a personal signature is appended. If any of the recipients are external to the company, then the business signature gets added. My personal signature tries to include the song I’m listening to at the moment, either on my own computer, or on the company jukebox. It does this by querying either iTunes or last.fm.

  1. require 'rubygems'
  2. require 'rbosa'
  3. require 'scrobbler'
  4. rules do
  5. smtp_server( "localhost" )
  6. smtp_port( 10025 )
  7. track = nil
  8. track_string = nil
  9. begin
  10. # Try and get currently playing information from either iTunes or last.fm.
  11. itunes = OSA.app( "iTunes" )
  12. if itunes.player_state == OSA::ITunes::EPLS::PLAYING
  13. track = itunes.current_track
  14. else
  15. user = Scrobbler::User.new( "29degrees" )
  16. track = user.recent_tracks.first
  17. end
  18. rescue
  19. puts [ $!.class, $!.to_s, $!.backtrace ]
  20. end
  21. if track
  22. track_string = "\"%s\" by %s off \"%s\"" % [ track.name, track.artist, track.album ]
  23. personal_sig = <<-EOT
  24. --
  25. Now listening to : #{track_string}
  26. Siggy Stardust r78
  27. EOT
  28. else
  29. personal_sig = <<-EOT
  30. --
  31. ASCII a silly question, get a silly ANSI.
  32. Siggy Stardust r78
  33. EOT
  34. end
  35. business_sig = <<-EOT
  36. --
  37. Regards,
  38. Carl Drinkwater,
  39. Director.
  40. http://29degrees.co.uk - Bespoke Web Application Development
  41. +44 (0) 161 953 6669 - +44 (0) 776 043 1463
  42. 29degrees Ltd is registered in England and Wales under company
  43. number 05952987. VAT Reg Number GB897293655. Registered office
  44. St. George's House, 215/219 Chester Road, Manchester, M15 4JE.
  45. EOT
  46. if recipients.all_in_domain?( "29degrees.co.uk" )
  47. append_sig( personal_sig )
  48. else
  49. append_sig( business_sig )
  50. end
  51. end

(Does anyone else think heredocs are ugly?)

Siggy tries to be intelligent when adding signatures to multipart emails. For me, the best results have come by adding the signature to the end of the last text/plain part of the email, and so that’s what Siggy does. It doesn’t attempt to do anything with text/html emails, because it shouldn’t need to.

If you want to play, download Siggy Stardust here. Run it by doing something like :

  1. ruby ./server.rb rules.rb

You’ll need to re-configure your mail client’s SMTP setting to use localhost and port 1234. By default, Siggy will proxy through to port 25 on the local machine, but you can change that by using the smtp_server and smtp_port methods as in my rules file.

The only other real helper functions are demonstrated in the final lines of my rules file :

  1. if recipients.all_in_domain?( "29degrees.co.uk" )
  2. append_sig( personal_sig )
  3. else
  4. append_sig( business_sig )
  5. end

You will probably need to write more to do the things you want, you’ll need to do that in server.rb.

To use the ‘now playing’ functionality, you’ll need the appropriate Rubygems installed. The iTunes lookup uses RubyOSA, and is only available on OS X.

Lastly, the rules file is reloaded each time you send an email through Siggy, so you don’t need to restart the server if you edit your rules.

The two files comprising Siggy Stardust, rules.rb and server.rb, are placed in the public domain. However, note that the gzipped-tar archive you can download above comes packaged with TMail, and is licensed under the LGPL.

# Tired of typing long method names?

A bit of Friday fun. Golfr saves you all the hassle of having to type out full method names by letting you use as few characters as you need. Look at the examples to see how it can save you valuable keystrokes.

  1. module Golfr
  2. def method_missing( method, *args)
  3. endings = Regexp.new( /[!?=]?$/ )
  4. ending = method.to_s =~ endings ? $& : ""
  5. ( look_for = method.to_s )[ endings ] = ""
  6. if found_method = ( methods.sort.select{ |m| m =~ /^#{look_for}/ }.first ||
  7. methods.sort.select{ |m| m =~ /#{look_for}$/ }.last )
  8. found_method[ endings ] = ""
  9. STDERR.puts "Calling #{found_method}#{ending} for #{method}" if $DEBUG
  10. send ( found_method + ending ).to_sym, *args
  11. else
  12. raise NoMethodError, "#{method}"
  13. end
  14. end
  15. end
  16. class Object
  17. include Golfr
  18. end

Then have fun!

  1. require 'golfr'
  2. a = []
  3. $><"Hello\n" # Matches '<<'
  4. a.uns "Cheese" # Matches 'unshift'
  5. a.ft [ "Pickle" ] # Matches 'unshift'
  6. puts a.insp # Matches 'inspect'
  7. a.fl! # Matches 'flatten!'
  8. puts a.pect # Matches 'inspect'
  9. puts a.n? # Matches 'nil?'
  10. puts "carl".c # Matches 'capitalize'
  11. Thread.a = true # Matches 'abort_on_exception='

Set $DEBUG=1 if you want to see what methods are actually being called, and feel free to do what you want with the code. It’s all yours.

# Missing songs in iTunes

This week, I was moving my iTunes library off an external HDD to a network share and somehow managed to completely badger it up. All the songs were still showing in iTunes and they were all on disk in their original places, but something had happened to their location in the iTunes database and were showing with an exclamation, indicating iTunes couldn’t find them.

After fixing these by trying to play the songs and manually locating them on disk, I was still finding songs which weren’t indicated by iTunes as missing, but actually were. So, I quickly wrote the below script to list all the broken tracks in my library. Unfortunately, there doesn’t seem a way to set the location automatically.

So yeah, I don’t know if this will be useful to anyone else, but here is the code …

  1. require "rubygems"
  2. require "rbosa"
  3. library_playlist = OSA.app( "iTunes" ).sources.find{ |s| s.name == "Library" }.library_playlists.first
  4. # Songs which are broken have a location of 'nil', but still have the
  5. # rest of the information.
  6. library_playlist.file_tracks.reject{ |t| t.location }.each do |track|
  7. puts '"%s" by %s, off "%s"' % [ track.name, track.artist, track.album ]
  8. end

# Determining 64-bitness

On a 32-bit machine :

  1. -1.size
  2. => 4

On a 64-bit machine :

  1. -1.size
  2. => 8

# extract_options!

The (old) “standard” way of extracting an optional options hash passed as the last parameter of a method call :

  1. def add_food( *args )
  2. options = args.last.is_a?( Hash ) ? args.pop : {}
  3. puts args.inspect
  4. puts options.inspect
  5. end
  6. add_food( "cheese", :edible => true, :drinkable => false )
  7. => "cheese"
  8. => {:edible=>true, :drinkable=>false }

This is something I’m seemingly doing more and more, and let’s face it – It’s ugly.

However, as of changeset 7217 (and the original ticket) of Rails, a method has been added to Array encapulate this. You can now do :

  1. require 'active_support'
  2. def add_food( *args )
  3. options = args.extract_options!
  4. puts args.inspect
  5. puts options.inspect
  6. end
  7. add_food( "cheese", :edible => true, :drinkable => false )
  8. => "cheese"
  9. => {:edible=>true, :drinkable=>false}

Such a simple addition, it’s hard to believe there wasn’t already a method to do this.

Update: And yes, I realise my examples above are crap – Hopefully you can see what’s happening though.

# Fibonacci Golf

  1. #!perl -l12e
  2. $_=1;($_,$?)=($?,$_+$?),print while$_<4e3

41 bytes, excluding the shebang line. Written for this.

  1. a = [ 1, 2, 3, 5, 6, 2, 3, 1, 4, 5, 4 ]
  2. puts a.inject( 0 ) { |c, i| c ^= i }

Find the unpaired number in an array. I can’t really think of a situation you’d need to do this, but it’s a really, really elegant solution and that’s why I’m posting it. It’s left to the reader to work out how it works. From.

More about this site...

Last Week’s Top 5 Albums (More »)

  1. Port Of MorrowThe Shins
  2. Broken Side of TimeAlberta Cross
  3. Uneasy Lies The CrownThe Domino State
  4. Conor OberstConor Oberst
  5. Ambulance LTDAmbulance Ltd