Friday, December 28, 2007

GEB part one

I just finished part one of Godel, Escher, Bach and I can honestly say it's been an exciting experience. I was first introduced to GEB by some friends at RubyConf. A week later at the local erlounge again it was commended. Since I had been reading a lot of pure tech books lately so I decided I would give GEB a shot. It's true that it's a book that 10 people could read it and each come to 10 different (valid) conclusions as to the purpose of the book.

Highlights for me thus far
  • The carollian dialogues between the Tortoise and Achilles. Especially the one which demonstrates the difficulty of trying to use logic and reasoning to defend itself.
  • The chapter on recursion. I think it's safe to say that most people that enjoy hacking on code would find this particular chapter enjoyable.
  • The numerous correlations between seemingly disjoint subjects. Obviously the book treats the relationship between G, E and B with special consideration but there are correlations on many more levels. You find yourself on the same page dealing with the intrinsic meaning of symbols and abortion, for example.
It's been some of the most challenging pages I've read in a while. I typically only have a few hours a week to spend with GEB and it's taken me several weeks to get 275 pages into the book. Ironically the most challenging part of the book thus far has been the Preface. I guess it shouldn't be that surprising when you consider the task of describing GEB holistically.

I would recommend this book to anyone who feels like they have been too intensely focus on one mental task too long. Often I find myself doing just that since it seems to be my forte. The various puzzles have been a nice trip outside the mental box (Strange Loop) I've placed myself in.

Recommendations for reading GEB
  • Attempt all puzzles. The completion of many of the puzzles is not of much importance in the scope of GEB. The mental exercise is of far greater value.
  • When you find yourself breaking out of a Strange Loop try and explain it to someone else. Here's something I came up with last night as I explained the Dual Nature of Formal Systems:
Imagine a chess board. Legal moves can be represented in algebraic chess notation (illegal moves could be represented as well). For example Scholar's Mate could be represented as:
  1. e4 e5
  2. Qh5?! Nc6
  3. Bc4 Nf6??
  4. Qxf7# 1-0
Now since Godel showed us that formal systems (in this case the allowed moves in Chess) can be mapped onto Number Theory you could imagine being able to create equations for entire chess matches that could be derived mathematically. What if something so simple as converting all the numbers in the various expressions were converted to base 26 and represented by the English alphabet. Since I'm already in the state of imagining atrocious coincidences I might as well imagine that upon transposing the numbers the letters reveals an entire book about the legal chess moves. Better yet, what if the book was not about legal chess moves but illegal! That would indeed be a Strange Loop.

Thursday, December 27, 2007

Kino 1.2.0: great on F8

Today I spent some time figuring out why I couldn't get Kino's transitions working on Fedora 8. Previously I was using version 1.1.1 from the livna repository and I noticed today that a tarball for 1.2.0 existed. Building and installing it to my home dir worked like a charm. All audio and video FX are working. During FUDcon I might seen if I could update the livna package for kino so that others could benefit. I'll test it out a bit more in the meantime.

On a side note I also gave pitivi a shot. It's far from it's first 1.0 release but I must I like the interface a bit more than kino. Plus, being written in Python makes it a little more hackable.

Wednesday, December 26, 2007

My first attempt at video editing on linux

It's been a while now since I sold my iMac. The one thing I've missed the most since that day has been the video editing (I haven't touched my mini-dv since). Tonight I decided I would give kino a shot. It's pretty good but it's definitely not iMovie. For some reason I was not able to get the transitions working on my system. I'll try and figure that out tomorrow. In the meantime I've uploaded a sample video of some clips of me and my wife on Topsail Beach, NC.

On a side note, people should give try. It's the first video service I've found that has first class support for ogg theora (big thumbs up). If you create an account be sure not to re-use a password as everything is done over HTTP (that's a big thumbs down).

*UPDATE* At least on my machine I wasn't able to get the aforementioned embedded video to play. I don't know anything about the cortado applet but apparently that's what is being used. Anyway, it plays on my machine with mplayer and at the moment that's the only thing that matters.

*UPDATE* I think the only thing I needed was the gstreamer-plugin rpm installed. Now it's working for me.

Sunday, November 25, 2007

Hotmail silently blocked my Amazon giftcard

I received an Amazon giftcard this year for my birthday. Actually, I didn't receive it. Let me explain.

I have a old hotmail account I give out if I suspect someone is going to give out my address (sometimes I just use mailinator). My mother-in-law was trying to be courteous since she didn't know if Amazon would give out my address so she sent the gift card to my hotmail account. When I logged in I noticed it wasn't in my inbox nor my spam folder. Forty-eight hours later it still hadn't arrived. I emailed Amazon and they told me the gift card could be reissued so we logged in and resent the card to my primary account. The email showed up instantly.

If hotmail really is cutting their own throat I hope the knife is sharp.

Saturday, November 24, 2007

Windows Tithe Day 2007

I just got back from a two week trip to Denver. My wife's family lives there so it made for a great place to take the Advanced Ruby Studio as well as spend the holidays. The second week I was officially on vacation and got to spend a lot of time simply relaxing and doing things I enjoy. One of those things is spread the open source love.

My mother-in-law has two year old Sony Vaio that originally came with Window XP Home Edition. For some unexplainable reason the wireless stopped working all of a sudden and by the time I was able to investigate the CD drive was no longer working. XP couldn't even mount my usb thumb drive. When I logged in as the admin user and looked under Device Manager it showed nothing there. While I don't claim to be an expert in Windows internals I felt quite certain something had compromised her system. It was indeed Windows Tithe Day.

Instead of repeating the vicious cycle I decided to fix the problem. Since I usually carry some form of a Linux live CD with me when I travel I decided to install Fedora on her laptop. Initially I installed 8 since it's the latest and greatest from the Fedora camp but I immediately hit some strange lockups that I believe were related to Xorg 7.3 and the radeon driver. I spent a few hours reading Every Single Post on an extremely long thread on Ubuntu's Launchpad that reported similar problems for some users with Gutsy. Since I had lots of success with Fedora 7 I put in my Live DVD and within 30 minutes had the basic system install and running. About 8 hours later (spread over a few days) there was one less Windows user in the world. My main goals for her system were:
  1. Wireless connectivity (auto connecting to the correct networks, etc)
  2. Dead simple picture importing from her Kodak camera
  3. An office suite
  4. Web browser with all plugins for using her favorite sites.
  5. Software for music notation
  6. Printing
One reason it took so long is that the configuration had to be flawless. Everything had to work perfectly or it was going to be a waste of everyone's time. That being sad most of my time was spent on numbers 2 and 5. On my laptop the second I plug in my Canon everything just works. A dialogue box pops up and asks me if I want to import the pictures. However the permissions weren't getting set correctly on her machine for some reason. I decided to create an /etc/security/console.perms.d/52-kodak.perms file that gave the console user write access to all usb devices. As for #5, I spent a lot of time evaluating the various open source programs available. Previously she had used Sibelius. Paying for Sibelius when all you need is a program to print out and archive musical notation is about like buying Photoshop just to resize pictures. GNU Denemo fit the bill nicely. It's a gtk frontend to lilypond and it worked like a charm. The best part is that if she really ends up liking it she can recommend it to her students and they won't have to shell out a few hundred dollars for No Good Reason. Denemo coupled with the free (as in freedom) music education curriculum from Connexions can take a grassroots piano school to a new heights.

So I guess if you are still reading this one of several thoughts have probably come to your mind:
  1. Why would this guy would spend so much time setting up this laptop and then ranting on his blog?
  2. I would have just installed a pirated copy of Windows XP Extreme Awesome Edition--it's suppose to be more stable, right?
  3. She should just by any mac. And when the day comes when it can't do everything she wants I would just tell her to by another one. Period.
Hopefully I'll address each of these issues, we'll see.

Basically I get extremely upset when software randomly stops working for people that 1) don't know how to fix the problem and 2) just don't have the time to worry about things like operating systems deciding to Just Not Work. I believe companies that engrain software like this into our culture are doing humanity a grave disservice. I actively try to correct the problem in anyway I can, whether by writing software myself or by finding something that will work for them that someone else has already written.

When I was in college I helped dozens of elderly people in my community learn to use technology to improve their quality of life. However many situations arose which forced me to step back and wonder if I was really helping them at all? Yes, on one level they are now capable of emailing pictures of their grandchildren to their relatives but the time they waste trying to figure out how ClickToGamble.exe got installed on their system when all they wanted was to install a plugin to view their sons video on YouTube, typically negates all time saved. Personally I don't want to waste an elderly persons time. Every moment is valuable. When I finally had to move for work I basically started giving them different advice: Buy a Mac.

That conclusion was reached prior to my realization that open source is the best solution to their problem, though I still partly agree with my original advice. You could replace "Buy a Mac" with "Get something that is going to work for the rest of your life no matter what it costs". Cost could be measure in a $3000 Macbook Pro or it could be 3 days of your life configuring an open source desktop environment. Either way make sure it's a one time cost. Anything else just isn't sustainable. Either your money or your time will run out. If there is one thing I can say about the Linux systems I setup it's that they will run until the hardware goes up to that big tech shop in the sky. I have been using Linux as my sole computing environment for the last 3 years and that's just been my experience. On a side note I consider the 3 days spent during initial setup to be valuable knowledge gained while at the same time I believe performing a postmortem on a Windows machine twice a year to be a complete waste of a person's life.

Hopefully I don't sound like a complete open source bigot. The truth is you can choose whatever computing environment works best for you (and I think you should), but as for me and my household we will use GNU/Linux.

Sunday, October 28, 2007

DSLs made easy

XOAP recently hosted the first Belgian Ruby User Group meeting and Peter Vanbroekhoven gave a great talk on metaprogramming in Ruby. I would recommend this to any of your Blub programming friends. For some reason the last 5 minutes or so of audio seems like it was cut out. The speaker gets through all the slides though. Perhaps they edited out the audience's questions.

Thursday, September 20, 2007

Sharing Xvnc sessions

We're a pretty diverse group at the RDU erlouge even though we haven't reached the point where we actually need a formal venue for our meetups. We're still bumming it out in cafes with free WiFi. Likewise we don't have a projector or anything for presenting our code. The easiest and most cross platform way to achieve pretty much the same result as a projector was to use VNC.

Here's what I do on Fedora 7:
#'s denotes root shell
$ means your normal unprivileged user

# yum install vnc-server vnc
$ vncserver :1 -depth 24 -geometry 1024x768 -AlwaysShared

Most of those arguments do not need any further explanation so I'll be brief. That command starts a server on display :1 (port 5901) and sets all the connections to shared. That's a nice flag to set (read the Xvnc manpage for more options) since we were having problems with people forgetting to specify a shared connection on the client side and thus disconnecting everything.

VNC is not the most efficient remote desktop protocol but it gets the job done. If a large group of people are connecting and bandwidth is limited you may try a few things to reduce the amount of bits that have to fly around. I like to use a lighter weight window manager. You can edit your ~/.vnc/xstartup and put in something like this:

[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
fluxbox &

Obviously the first to lines are boilerplate.

If you are ever in a situation where you don't feel like the wireless network you are on is safe I would recommend tunneling your VNC traffic through SSH. I don't think any VNC servers advertise their security and the traffic definitely isn't encrypted. Just give everyone who you want allow access to your machine an account then have them log in as follows:

$ ssh -N -T -L 5901:[VNC server ip address]:5901 &

That creates the tunnel. Then just tell the users to connect to their local point (which forwards to the host)

$ vncviewer -ViewOnly -Shared localhost:5901

NOTE: The '-Shared' option is only really needed if you are connecting to a server that doesn't enforce sharing.

Wednesday, September 19, 2007

Using git to cope with crazed svn repositories

If you ever find yourself working with a gnarly svn repo you may want to give git-svn a try. You will be able to do your collaboration with git and then dump your changes back to svn. The truth is many large projects are not yet ready to ditch svn completely and there may exist tooling already for svn that your team needs (and doesn't have time to rewrite). For this reason exists git-svn.

Initialize your svn aware git repository:
mkdir mywork; cd mywork
git svn init
git svn fetch -r [revision you care about]

The reason I'm encouraging you to only grab the code you care about is because if you are working with a truly crazed svn repository things can get unnecessarily complex. When I did a full svn import of the root on the svn repo where I work it took over 3 days to finish on a good connection. The truth is there was only one branch that I really cared about.

If you are working on a more complex project and having to deal with other groups that are using svn you may have to do a slightly more sophisticated initialization:

git svn init -T path/to/the/repo/you/want/to/commit/to -b dir/that/has/branches/of/other/teams

The main thing to understand is that git-svn provides two-way communication between git and only one branch in svn. The path you specify for '-T' needs to be that one branch. It doesn't actually need to be the real trunk from svn's point on view--it's just the particular path you care about.

Once you have initialized your repo you will need to do some fetching. Again, you don't want to fetch more than you need. One thing that was not intuitive for me was how the fetch works. I immediately tried to check the latest revision and nothing was getting pulled down. The trick is to pull down revision that actually have commits. Use 'svn info' to find out the last revision where a particular path was changed. You will need to do this for your 'trunk' and any other branch you care about.

Monday, August 27, 2007

Erlang Bit Syntax II

Since my previous post on the subject was so lame you should take a look at a better article on the subject.

Saturday, August 11, 2007

Erlang bit syntax

I've been hacking around with Erlang off and on the last few weeks because I think it will be immediately useful for a few problems I'd like to solve. When people are first exposed to Erlang they are often impressed by its support for massive concurrency and crazy "assign once" variables. Aside from that I've found Erlang's bit syntax to be a pleasant surprise.

What would someone want to do with a bunch of nasty bits? Well the example in the PragProg book shows how to create a SHOUTcast server for streaming MP3s. Using the bit syntax you can elegantly chop up the binary blobs to read the metadata.

Here's an (unrelated) example taken from

DgramSize = size(Dgram),
case Dgram of
<<?IP_VERSION:4, HLen:4, SrvcType:8, TotLen:16,
ID:16, Flgs:3, FragOff:13,
TTL:8, Proto:8, HdrChkSum:16,
DestIP:32, RestDgram/binary>> when HLen >= 5, 4*HLen =< DgramSize ->
OptsLen = 4*(HLen - ?IP_MIN_HDR_LEN),
<<Opts:OptsLen/binary,Data/binary>> = RestDgram,

I appologize for the lack of indentation. The method I have used previously for escaping code didn't like Erlang's use of '<<' instead of blogger's PRE tag. It's that specific syntax, however, that is used for Erlang's bit packing and unpacking. Equivalent code written in most languages would get a little nasty. If you would like to see documentation on the syntax be sure to check out this site.

Thursday, June 14, 2007

Ruby closure shootout

Ok, so I too have been bitten by the arity differences between and lambda so a few months ago I tried to find the Ruby spec to get a better understand. It was then I came to realize that the only true Ruby spec is defined by the C implementation. While such a spec may allow for rapid improvements to the language it comes at the cost of warts--and Ruby is not without it's fair share. I stumbled across this site today that is possibly the best 'research' compiled on Ruby's closures that I have seen to date. It does a great job of exposing Ruby's warts while at the same time demonstrating the power of closures in Ruby.

The article (it's really just a script you can feed the interpreter!) was encouraging in that it showed me I really should spend a little time in the MRI perusing the source for these sorts of tidbits. I can really appreciate all the work that the groups heading up the various Ruby implementations are doing to formalize a Ruby spec.

Saturday, June 2, 2007

Black-boxing Google Translate

It seems like the more I watch the Mountain West sessions the more I stumble across solutions to itches I've had recently. Just yesterday at work I was hacking with a friend on a simple CLI for Google Translate and we were struggling a bit getting 'curb' to do exactly what we wanted. After watching James Britt's session on Black-boxing with Ruby I realized that mechanize would probably be a better choice for what we were trying to do. 10 Minutes later:

require 'rubygems'
require 'mechanize'

agent =
agent.user_agent_alias = 'Linux Mozilla'
page = agent.get("|#{ARGV.shift}")
translate_form = page.forms[0]
translate_form.text = ARGV.join(' ') = "UTF8"
translate_form.hl = "en"
results = agent.submit(translate_form)
puts Hpricot(results.body).search("//div[@id='result_box']")[0].to_plain_text

# Examples
ruby translate.rb zh-CN "I love to eat tacos on Tuesdays" => 我爱吃tacos周二
ruby translate.rb es "I love to eat tacos on Tuesdays" => Amo comer el tacos el martes

While these may not be accurate translations, this script definitely works for testing out i18n functionality until the real translations come in. If and whenever Google decides to release an API for their site it will be painless to throw this script away.

Programming Rule #42

"Every problem has already been solved. It is Open Source. And it is the first result on Google"
--Ara T. Howard (I don't know if he's actually the one who said that first, someone correct me if I'm wrong)

I spent some time this weekend watching the Mountain West Ruby Conf's videos and I must say what I've seen so far has been great (now I'm really exited about the Ruby Hoedown). The session on Ruby Queue is going to be immediately useful to me in my effort to distribute selenium tests over a linux cluster. It's actually quite amazing that the solution I had cooked up approached the task of clustering from almost the same way--simply using a queue to feed shell tasks to an array of nodes. It's quite ironic in light of Ara's quote on Rule #42 and his project that basically sent mine to the grave.

Luckily my solution was only the product of a few weeks of work off and on. In < style="font-weight: bold;">it's that simple. So, I'm going to take my project off rubyforge and stick it somewhere else. The one thing that I really need that RQ doesn't handle is clustering with Windows machines. Since I need to run tests with IE I'll have to spend some time to see if this is something that could be worked into RQ. I have absolutely zero experience with Windows and NFS so I don't have any idea how much work would be needed at this point.

Tuesday, May 8, 2007

": No such file or directory" error from bash

I hit a strange problem this morning that I hadn't seen before. I tried to run a ruby script and bash kept telling me ': No such file or directory'. I then tried feeding the script to the interpreter directly and things worked as expected. After double and triple checking my shebang line everything seemed correct. It then occurred to me to think about where I had gotten the particular script in question from. It was generated by the Selenium IDE while I was on a windows test machine a few weeks before. As many already know line breaks in the windows world end with simply a carriage return and not a carriage return linefeed pair. I used the wonderful dos2unix utility to sanitize my script and then everything worked as expected.

Friday, April 27, 2007

Get to know your inner eigenclass

I spent some more time looking for interesting articles on ruby metaprogramming. After deciding upon my method of search I quickly fired off an amazing google query for (hold your breath...) "ruby metaprogramming". I came across this article in no time and when I saw how horrible the site looked I quickly closed the page and begged my eyes for forgiveness. A little while later I came across another blog that was praising that particular article so I figured I should at least read a bit. It turned out to be a very well written article that helped me understand the concept of class vs. metaclass (aka eigenclass). I recommend viewing that page in elinks.

* Observant readers will note that the theme used in the aforementioned site is the exaxt same as the author of this blog. It's now become patent to me how hard it is to read. You should probably be reading this site in a feed reader anyway.

Wednesday, April 25, 2007

If you can read this you are too big to play here.

I remember when I was in preschool I used to climb on a huge tree in the middle of the playground. My friend David and I would catch caterpillars and then squish them on the steps of the school to see what color they were inside. That tree is barely standing now and I've long since realized that squishing things for mere novelty is a little strange. Another thing I discovered later in life was a sign that was hanging from the surrounding fence stating, "If you can read this you are too big to play here".

After my first pass reading this article on InfoQ I had the an all too familiar feeling as if there was something going on that missing me entirely. I read through it a second time and the uses of eval, class/module_eval and instance_eval are starting to become more apparent. Read the code and pay close attention to the use of eval. It might not be so evil after all.

Tuesday, April 24, 2007

JRuby 0.9.9 is out in the wild

If JRuby isn't on your radar it should be--especially with today's announcement of JRuby 0.9.9. The investments in optimization are starting to pay dividends. I think one of the most impressive aspects of this project is the momentum.

Aren't familiar with JRuby? Watch this video of a presentation by Ola Bini last month on JRuby 0.9.8:

Migration gotcha

Apparently sqlite3 is more forgiving than mysql when it comes to migrations. I found out today that there is no need to specify the ':id' column and if you try it with mysql5 you will get an error similar to:
Mysql::Error: #42000You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(11), `suite_id` int(11) DEFAULT NULL, `text` varchar(128) DEFAULT NULL) ENGINE=' at line 1: CREATE TABLE surefire_notes (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY(11), `suite_id` int(11) DEFAULT NULL, `text` varchar(128) DEFAULT NULL) ENGINE=InnoDB
The problem has to do with the 'PRIMARY KEY(11)'. I pasted the above command directly into mysql and removed the '(11)' and everything worked just fine. With some more googling I came across this site which further confirmed my discovery.

Monday, April 23, 2007

The best explanation of metaclasses in Ruby I've found

I stumbled across "seeingMetaclassesClearly.html " today. I don't know how I never came across it. It's definately the best explanation of metaclasses in Ruby I've ever read. Now the whole "class << obj; def meth; puts "hello from the metaclass"; end; end;" syntax makes sense. Previously I had used "obj.extend(module)" before but the former is obviously more convenient if you are in a class definition.

Wednesday, April 4, 2007

getaddrinfo: name or service not known

Once again I find myself trying to get a ruby app working on a windows machine. I can hardly express bad I feel for anyone who is plagued to work in such an environment full time. The last time I was struggling to understand how Ruby's in-process threads on win32 are not concurrent. This time around it's trying to understand why getaddrinfo() was failing.

Basically I'm working with DRb which by default uses TCPSocket as the default protocol. Socket.getaddrinfo() was telling me 'name or service not known' when it was trying to connect to the DRb server on my unix host. After hours of googling around learning about getaddrinfo() on windows and cygwin I came to realize that my problem was probably not related to what most of the google (and yahoo) results were returning. Apparently there was a time when that call would simply fail or was not implemented in cygwin. It turned out my problem was actually related to the hostname of the machine it was working on: 'LENOVO-A0EFF48'. I can't say I totally understand the relationship between cygwin and windows understand of a machine's hostname but I eventually changed the hostname to 'localhost'. I rebooted I got a different error because my VPN was choking (and I suspected it to be related to the hostname change). I then changed the hostname to 'laptop' and rebooted. Voila, my VPN and getaddrinfo() worked. Now I think I'm back to fighting Ruby threading issues on windows.

When I get around to it I'll look microsoft's getaddrinfo() source and figure out why it was choking on 'LENOVO-A0EFF48', oh wait....

Wednesday, March 14, 2007


I installed FC6 on my friend's PC. He had been wanted to try out linux for a long time so when I came to visit him in Bilbao we sat down and I gave him a crash course in unix.

The things he was most impressed about:
  1. OpenOffice (he really just need a nice way to make PDFs and presentations)
  2. He could use skype (he calls home to Brazil a lot)
  3. He could use all his other messengers
  4. Lots of software he was already familiar with is open source (he just didn't know it)
  5. It ran on his old computer extremely well and his hardware Just Worked(TM)
  6. He could learn the basics in an afternoon.
He doesn't really have time to play around with all of the other open source software I installed and I obviously didn't teach him anything about the commandline or anything of that nature. He really just wanted a machine in his living room for his family and visitors to use and not have to be worried about viruses and endless maintenance. For those switching to linux from lesser operating environments the hard part is just picking a distro and getting it setup initially. Many users use so few programs that once everything is setup they are set for a few years.

Tuesday, March 13, 2007

mutt header caching

I was wondering why when I built mutt 1.5.13 I only noticed a slight performance boost over 1.4.x when headers were being loaded. I finally realized I never configured header caching!! Here are my newly revised compile time options:

./configure --enable-pop --enable-imap --with-gss --with-ssl --with-sasl --enable-hcache

From there it's just a matter of adding 'set header_cache=/path/to/cache' to your muttrc. Go ahead, try it out for yourself!

Getting mutt to autocomplete multiple email addresses

I have a query command specified in my muttrc. Basically it's perl script that searches the corporate ldap server. It works just fine whenever I type 'Q' from the pager and I can even type 'A' to append to the query. My problem is that I couldn't figure out how to select multiple entries. I googled for a while and the best thing out found was typing '^T' while entering text in the To: field. That allowed me to use my query command for sending emails to multiple people. My guess is that it will also work for any other fields as well.

Sunday, February 25, 2007

7 Habits For Effective Text Editing 2.0

I've been watching videos on Google lately. Here's one that I really enjoyed and it's inspiring me to do a talk at my work on vim. It seems like every vim hacker has their own bag of tricks that help their productivity and cross-pollination is a good thing.

Seriously, find time to watch a little bit of this video. Actually, more importantly--find time to learn more about your text editor and then hack! This video encouraged me to find ways to leverage my vim knowledge in other areas. I've finally started using mutt for email (for some reason I thought it was going to be hard to get working and had been putting it off for a long time).

Sunday, February 18, 2007


I stumbled across this program last night and figured I hack it out for those of us who don't met the installation requirements. It's been something that has annoyed me about every cell phone carrier I've ever had--not having an easy way to know my monthly usage. Actually, I can't complain too much, I remember when I had SunCom years ago and I couldn't even get that information from a website. The truth is Verizon's site isn't that much fun to use and I never check it more than once a month. Enter saldo.rb:

(I don't have enscript configured on this machine, please forgive me for how blogger displays this)

#!/usr/bin/env ruby
require 'rubygems'
require 'curb'
require 'hpricot'

username = Curl::PostField.content('IDToken1', ARGV[0])
password = Curl::PostField.content('IDToken2', ARGV[1])
realm = Curl::PostField.content('realm', 'vzw')
charset = Curl::PostField.content('gx_charset', 'UTF-8')

c =
c.url = ""
c.enable_cookies = true
c.http_post(username, password, realm, charset)

c.url = ""
Hpricot(c.body_str).search("//table[@class='modStdTbl']").each do |table|
(table/"//tr").each do |row|
#I couldn't get the CGI library to unescape ;
(row/"//td").each {|c| print c.to_plain_text.gsub(/;? /, "") + "\t\t"}

Saldo is a term used in Spain to refer the the remaining balance on your phone. Since most people over tend to use the 'pay as you go' plan it's important to always know how much you have left. All the providers I know of in Europe make that fairly painless to find out from your phone. Until I get that from Verizon I'm going to be running this as a cronjob and mailing it out to myself and my wife.

I'm not sure how watchmycell is implemented but my guess is it's something similar. I couldn't find any sort of web services provided by Verizon so I had to use curb and hpricot.

Saturday, January 27, 2007

Windows is driving me to the bleeding edge...

of my sanity. Did you know that Ruby's green threads on windows are worthless? Ok, they aren't completely trash, I mean, they do indeed work but the problem is that they don't run in parallel. Kind of a bummer, eh?

It's especially frustrating when I hacked up a dsl and a RESTful service for executing commands on remote clients in a few hours and I have spent an entire day of my life trying to get it to work properly in windows. I guess this is where Ruby's unix prejudice really starts to show (personally, that's fine with me).

So, after finally figuring out why my DRb server was unresponsive after spawning a new thread I figured I would try using JRuby since it uses Java Threads. Let me first say that I'm quite impressed with the work that the JRuby team is doing. However, due to a bug that exists in the 0.9.x branch I was still unable to get DRb to spawn the thread properly either (for totally different reasons). On a sidenote my friend ruby-debug doesn't currently work under JRuby either. I will dig deeper into that problem later, but after spending and 2 hours and getting 'no where' I have moved on.

So I'm switching to edge YARV. That's the bytecode interpreter that's shipping with Ruby 2.0. I read that there are more threading options available in YARV and I'm interested to see if it helps me out at all.

Thursday, January 18, 2007

Mark, we need arrive at a clearer definition of the word free...

Because it's really starting to bother me that you say the word 'free' as if you don't know there are two distinct meanings in the open source ecosystem. I will choose freedom before I choose free beer. Let's call your definition of free 'FREE' and we'll call mine 'free'.

While I think it's important to many people that things are FREE I believe the greater good is freedom. Freedom to tinker, break, improve and understand. I'm worried you think that if everyone just starts using FREE software the world will be a better place. I posit that if the world (for some definition of 'world') understood the freedoms that come with free software and used it to it's full potential the world would indeed be a better place. From what I've seen on the net recently the EU might be starting to understand this.

Let's put our motives aside and not label companies that have made great contributions to freedom as not 'FREE'. The truth is Mark the freedom is in the source.

Friday, January 12, 2007

Overloading a method within a class.

I came to an interesting realization today what I came home from work and started to look through what had been posted to comp.lang.ruby. The language I program in has drastic effects on my design. Actually, I guess I've always thought to that be true. That's probably why I prefer to do certain things in one language over another. Anyway, enough of my being theoretical. Read this.

What I find fascinating is that in over two years of hacking ruby it has never even once occurred to me that I couldn't overload a method within a class. Why? Because Matz and the other Ruby commiters have found it to be a Bad Thing(TM) and Ruby encourages you to do good things. Yeah, yeah, if you read the whole thread another reason for not implementing it is because it would be hard to do. With that aside I've already started to loathe seeing multiple constructor signatures in a class and that's pretty much the same thing. Just make a static constructor and give it a name that actually means something. None of this 'new Foo(x); new Foo(x,y); new Foo(x,y,z)' trash.

Wednesday, January 10, 2007

Kernel#gets vs. IO#gets

I made an interesting discovery tonight while hacking on widi (it's actually quite embarrassing that I never came across this before). Whenever you are trying to read from stdin in ruby you typically just type 'gets' and don't think twice. I found out there are actually two different 'gets' methods, Kernel#gets and IO#gets.

Usually you don't notice the difference simply because if ARGV doesn't exist Kernel#gets simply reads from stdin. However, tonight I started building out some of the scm wrapper functionality of widi and naturally I was adding command line arguments. This caused widi to die a painful death. It's last words were:
kill #: widi.rb:27:in `gets': No such file or directory - kill (Errno::ENOENT)
from widi.rb:27

To fix the problem I googled a bit and realized I needed to explicitly tell ruby to check stdin using the global variable $stdin (IO#gets is private so don't even bother trying to call it!). Not exactly intuitive but I guess I can't complain too much.

Sunday, January 7, 2007

I will learn something new about vim every day of my life until I die.

I never cease to be amazed by the raw power of vim. Over the last year it has become my editor of choice for ruby code. I even find myself closing my IDE and using vim to edit java code from time to time when things get serious (I swear I could write a web app using only vim macros).

So, I suggest you take some time and read Jonathan's McPherson's blog entry on efficiently using vim.

Tuesday, January 2, 2007


Apparently no one uses ruby-breakpoint anymore. For some strange reason it just stopping working for me all together (that's what really disturbs me). I would hit a breakpoint and it was as if the proper binding simply wasn't being set. I didn't have access to the scope in which the breakpoint was executed (that's not very helpful).

Luckily I came across 'ruby-debug'. Everyone on #ruby-lang says it's cooler anyway.

Monday, January 1, 2007


I frequently find myself writing the exact same method over and over with only minor differences between them (I'm sure there are plenty of design patterns to get around this in every language). One way of getting around this in ruby without much fuss is 'define_method'. Here's a snippet from Widi:

['header', 'footer'].each do |m|
define_method('generate_' + m) {
@widi_config = WEBrick::Config::Widi
file = @widi_config[m.capitalize.to_sym]
file =~ /rhtml/ && File.exists?(file)
data = open(file) {|io|}
elsif file.nil?
constant = self.class.to_s + '::DEFAULT_' + m.upcase
constant.split('::').inject(Object) do |x,y|
Once that code is run the encompassing class will have two methods called 'generate_header' and 'generate_footer'. This approach would be more justifiable if I needed more than just two methods so I may end up ripping it out.

One thing that did not behave how I expected was Module#const_get. It doesn't handle the ::'s nicely and I had to use an idiom I found in The Ruby Way.


Santa brought Denver a lot of snow for Christmas this year. I guess this is what happens when you get snowed in and decide to read a book on the linux kernel.

From snowtux


my google reader feed