subscribe secretGeek RSS secretGeek .:dot Nuts about dot Net:.  

Q: Where am I?

A: You're sitting at a computer, reading Leon Bambrick's personal thoughts on programming.

Wed, 09 Apr 2014 17:56:42 GMT

The Canine Pyramid

So a computer guy is laid off from his computer job. He soon gets sick of sitting arond at home and he decides he wants to go for a walk everyday. There are a lot of physical and psychological benefits to going for a walk every day. He notices people taking their dogs for a walk and realises that taking a dog for a walk is a great way to ensure you get regular exercise.

So he makes up a small flyer: dog-walking as a service. And he walks down to each of the houses in the street that has a dog and drops a copy in their letter box.

The next day on his walk he walks even further, covers the next three streets. If a house doesn't visibly have a dog, he walks past them. If they do have a dog he puts a flyer in their letter box.

The calls start coming in thick and fast. He is inundated with more dogs to walk than he can service himself. He institutes strict rules, for maximum quality. No more than two dogs on a walk. $30 a half hour or $50 for a full hour.

He formulates a new plan: he goes to each of the houses that don't have dogs, and puts different flyers in their letter boxes: Want regular exercise? Become a dog walker! Great pay, great lifestyle, it's the casual social exercise job you've been looking for. Why pay money to exercise when you can be paid instead!

He gets books out of the library: the dummies guide to dog walking. He learns first aid for pets. He gets hats printed with the Dogercise logo. He gets bright t-shirts printed up. People are volunteering to walk dogs before work and after work. The elderly are walking little dogs. Young women love to take guard dogs with them on their evening jog. He institutes a dog-matching algorithm that pairs each dog to just the right walker.

He builds a website for managing the booking of dog walks. He builds a smartphone app, customers use it to book their dog walks, to trade tips and to thank their walkers. There are social meets and barbeques.

He gets a map of the greater suburb and divides it into small areas that surround the area he already letter-dropped. He tells his most proficient dog-walkers that they can pick an area and letter drop it, manage those territory for themselves. They take a percent of the earnings from the walkers they manage. They organise social events, perform letter drops, sort out issues as they arise.

Now on the map he draws up new areas, just at the edge of the areas that are already being managed. The best walkers from the existing areas are allowed to nominate themselves for those areas.

In a very short time, the business has spread out, whoosh, and his dog-walking empire covers the entire globe. He stops for the first time and realizes: I'm actually more of a cat person.

Read On...

Mon, 07 Apr 2014 09:51:05 GMT

Humans: A Tragedy.

One of the saddest pieces of trivia in the world is the number of people who follow Uberfacts on twitter.

Apparently this 'verified' account has 6.46M followers. I was hoping that 6.46M meant 6.46 Morons but sadly, it means 6.46 *MILLION* Morons.

Uberfacts crime? It presents extraordinary 'facts' without providing references of any kind.

Extraordinary claims require extraordinary evidence

Extraordinary claims require extraordinary evidence was a phrase made popular by Carl Sagan. It is the heart of the scientific method, and a model for critical thinking, rational thought and skepticism everywhere.

Since Uberfacts provides no references for any of their 'facts' it takes the reader a non-trivial amount of work to determine if they are true or not.

Many of them are too ill-defined to be either true or untrue on their own. And many of the others, if you do happen to spend the time it takes to research them, are somewhere between partly or wholly incorrect.

(Incidentally, researching these sort of 'shock-value' research-lite facts also leads you into a depressing quag of equally inane sites.)

I love trivia and triviality. The twitter account QIkipedia (related to the BBC Televsion show QI) is a much better example of a trivia sharing service hosted on twitter.

Comparison of Uberfacts with QIkipedia

Never provides sources or references Often provides references*
Does not retract errorsRetracts errors
Does not enter into discussionEnters into discussion
Hides advertisements as 'facts'No trickery.**
6,460,000 followers553,000 followers

* I would prefer it if the QI team were even more forthcoming with references. But at least due to point 2 and 3 there are avenues for corrections if any of the followers do find errors.

** When, for example, they promote Molly Oldfield's book, they're clear that she works for them. Etc.

And note that none of this is directly related to whether the facts are right or wrong. If all of the damn 'facts' were right, I probably wouldn't care if they messed up all the other points.

According to this gushing piece at ZDnet the more "outrageous" uberfacts are linked to a tumblr account where they are "explained in more detail". This is also, like everything Uberfacts related, quite untrue. Even at the tumblr account you don't get more details. All you get are pictures, with a quoted "source" of Uberfacts itself. Like this:

Anatidaephobia is the fear that somewhere in the world, there is a duck watching you.

Anatidaephobia is the fear that somewhere in the world, there is a duck watching you.

Are you kidding me? Is this true? Is there really such a fear? It doesn't sound particularly true, though there is a certain ring of familiarity that I can't quite put my finger on. Let's see if it's mentioned at Wikipedia.

Yes, here it is, in their 'List of Phobias under the heading "Jocular and fictional phobias":

Anatidaephobia the fictional fear that somewhere, somehow, a duck is watching you. From Gary Larson's The Far Side.

And here is the actual source:

So it's a joke from Gary Larson, no more factual than 'luposlipaphobia' (the fear of being pursued by timber wolves around a kitchen table while wearing socks on a newly waxed floor).

What's the harm, hey!?

But why am I being such a grouch about this? What's the harm?

As Aristotle used to remark on many a sunny day in Athens:

It is the mark of an educated mind to be able to entertain a thought without accepting it.

Shouldn't we just be entertained by these facts? Chill out and let it go? As they say in the subtitle 'Bringing you the most unimportant things you'll never need to know', these things are chosen for their innocuosness. So what if they're right or wrong?

But these 'uberfacts' don't belong to the category of thoughts that bring entertainment for their own sake. They are almost entirely "facts" which are only entertaining if they are actually true. If they're not true, they are pointless at best, time-wasters at least, and potentially harmful.

Here's the scary bit: these uberfacts take on a life of their own, and Darwinism isn't quick enough to take care of the people who spread them.

For example there are serious articles discussing the likely causes of anatidaephobia, and helpful guides for those who suffer from this worrisome-- and growing-- malady, at sites such as, "serious facts", and "factual facts".

Don't trust that sites like Snopes will do all the work of sorting out the lies from the truth. You can't leave it up to Snopes. It's everyone's responsibility: mine, yours, everyone's, to stop repeating (retweeting, posting, regurgitating) the endless stream of lies and bullshits.

Uberfacts: unfollow.

Read On...

Fri, 28 Feb 2014 09:14:26 GMT


Email and IM should - (like facebook, twitter and stackoverflow) - allow for a star/like/fav of an email or message which acts as an positive acknowledgement without requiring any other response or elaboration, nor consuming an entire message unto itself.

Land-line telephones could also have a button for this: you toggle it to the "on" position and it will "uh-huh" and then "uh-huh" again every 30 seconds as your elderly aunt describes her neighbour's friend's pet dog's medical dilemmas.

Read On...

Thu, 20 Feb 2014 09:34:31 GMT

OfficeQuest... Gamification for the Office Suite

While the evil makers of Candy Crush Saga are busy filing for their IPO, now is the time for Microsoft to add awesome Gamification features to their stalled Office Suite.

With help from Indie game developer Thomas White, here's our vision for "OfficeQuest". If you're listening, new Microsoft CEO Satya Nadella, this is the fresh idea your looking for to give the company a jolt of adrenaline and turn your CEOship into a new golden age for Microsoft!

MS Office with custom ribbon, that let's you purchase 'Stars'. Dialog says: 'Achievement Unlocked: Complete a sentence. Earn 1 Star.'

Dialog says: 'Emboldening Text... Instant Embolden for 1 Star.'

Googling for 'What Satya Nadella should do' showed me that a lot of people have already made a lot of suggestions for the good man to follow up. But my real suggestion is that Windows should build a real app store. With first class support for install, update, uninstall and purchase of real desktop apps. That would be awesome.

Read On...

Wed, 29 Jan 2014 09:59:41 GMT

New product launch: NimbleSET

Hi there. So I've finally released my third product. After a discombobulating amount of toil, I've put out NimbleSET, your Venn-diagram SET comparison buddy. Download it, use it, register it, use it online, be amazing etc.

It's a very, very simple little tool, and I don't expect to make a mint from it. But it was a very good opportunity to sharpen up my application-production line. The next product will be easier, and so will the one after that, etc.

I've just used it to compare the ingredients between several different cocktails, in order to work out which ingredients offer the most utility. As a result I've decided to purchase limes and Bacardi. You could be drinking cocktails too, if you had a copy of NimbleSET.

NimbleSet comparing ingredients between a Mojito and a Strawberry Daiquiri

Read On...

Mon, 06 Jan 2014 11:54:30 GMT

Programming The Robot from Diary of a Wimpy Kid

My daughter Lily has been reading her first ever novel, ' Diary of a Wimpy Kid' (recommended by Joe Cooney) and one part of the book led her to do some programming with me. Yay for reading! Yay for programming! and yay for my daughter!

Here's the story that inspired her:

We got to work. Someone had the idea that you can say your name to the robot and it can say it back to you.

Robot says "Hi BOB it is very nice to meet you BOB."

But then someone else pointed out that you shouldn't be able to use bad words for your name, because the robot shouldn't be able to curse. So we decided we should come up with a list of all the bad words the robot shouldn't be able to say.

We came up with all the regular bad words, but then Ricky Fisher came up with twenty more the rest of us had never even heard before.

So Ricky ended up being one of the most valuable contributors on this project.

Right before the bell rang, Mr Darnell came back in the room to check on our progress. He picked up the piece of paper we were writing on and read it over.

Mr Darnell looks over the piece of paper

To cut a long story short, Independent Study is cancelled for the rest of the year.

Diary of Wimpy Kid, Jeff Kinney

I said to Lily we could make a program like that and—get this—she was actually excited about the idea. So we sat down together and made a program. I asked for her help with every bit of it. Here is how it went:

namespace feedback
    using System;
    using System.Linq;

    class Program
        static void Main(string[] args)

            while (true)
                Console.WriteLine("What is your name?");
                var name = Console.ReadLine();
                Console.WriteLine("Hi " + name + " it is very nice to meet you " + name + ".");

Next we put in a secret codeword, 'Exit' that you could use when you want to stop.

if (name == "exit")

And then a secret codeword so if it recognised you it would change color:

if (name == "Lily")
    Console.ForegroundColor = ConsoleColor.Magenta;

Lily said we could make it say your name backwards! So I tried this...

var backwardsName = name.Reverse();
Console.WriteLine("Hello " + backwardsName);

But instead of printing the name backwards, this printed...

Hello System.Linq.Enumerable+<ReverseIterator>d__a0`1[System.Char]

Try explaining THAT to a 6 year old.

It was easier to do it like this:

var backwardsName = "";

foreach (var letter in name)
    backwardsName = letter + backwardsName;

Console.WriteLine("Hello " + backwardsName);

That worked much better.

Now Lily had an even better idea. What if the robot said a different word for every letter of their name.

My work friends will know that Phonetic Alphabets are something we play with quite a bit, in order to make dealing with IT support easier. But Lily independently came up with this idea, without any prompting from me.

So if you're name is Leon it would say "Hello Lemon-Echo-Octopus-Nose". Or words to that effect.

                var wordyName = "";
                foreach (var letter in name.ToUpperInvariant())
                    letterNumber = Convert.ToInt32(letter) - 65;
                    if (letterNumber >= 0 && letterNumber < AlphabetWords.Length)
                        wordyName += AlphabetWords[letterNumber] + " ";
                Console.WriteLine("Hello " + WordyName);

And this relied on coming up with a big alphabetic list of words. We had fun doing this together.

static string[] AlphabetWords = { 

Well, there it is. And a big thumbs up to Jeff Kinney for teaching people from an early age that user input is not to be trusted.

Read On...

Sun, 05 Jan 2014 12:18:01 GMT

Happy new year 2014

I am truly beat! It's been a tough few days.

Dibbs—mon primo masseuse—sits on the floor in front of me, rubbing at my tired feet, while Carolyn, my sous masseuse, is working on my shoulders, trying to remove the knots. Cornish, the Somelier, is trying to find the perfect vintage to accompany the poached duck that Withers (my new Chef) is preparing for brunch. I try one, then the other. I'm not sure which is best. "Better buy both wineries," I say, and Cornish dashes off to make the arrangements.

My newly appointed personal DJ, the renowned "H-Dog", is fading out some Miles Davis, and fading in a little Acid Jazz. He's a quick learner, H-Dog, and knows from the slightest furrow of my brow exactly what sort of music will best suit my state of mind at any moment in time. A lesser DJ, for example, would've only played Sweet Child O Mine two times in a row. But H-Dog saw the smile on the corner of my lips, as I stepped out of the limousine this morning, and knew I needed to hear Sweet Child O Mine five times in a row, before switching straight over to Tangled Up in Blue followed by an hour of Led Zeppelin: Just The Guitar Solos.

Even up here on the penthouse floor, the glare from the ocean is striking my sunglasses at too oblique an angle: I might need to take the private jet back to Whistler for a little R&R amongst the snow-capped mountains.

I'm suddenly struck by a thought. Don't you hate it when a thought is like an itch: an itch deep inside your scalp. You feel your brain crawling; crawling and itching and thinking and thinking. You would do anything to kill the itching, crawling thought! I clap my hands and Karl, my recently acquired Master Of Knowledge Gathering, rushes into the room. "Orange!" I shout. "Orange. Is the color, Orange, named after the fruit, or is the fruit, Orange, named after the color?"

"Why Sir, I believe..."

"Zip it!" I shout. "I don't want to know what you believe. Do some research and make sure, then get back here with an answer." A good Master Of Knowledge Gathering is something everyone should have. One tires of doing all one's own GooglingTM.

And just think! Only a week ago I had to GoogleTM for myself! I lived in ordinary premises, I had no secondary masseuse, not even a primary masseuse. I had to choose my own music: like a chump! I was living like a chump! ME!? And why? What changed?

The littlest thing. I can hardly remember it now; what propelled me from mundanity to magnificence? It was before yesterday when I went shopping for luxury yachts. It was before the day before that when I test-drove the Zonda and told them I'd like something with a little more Oomph. It was before the day before that, when I purchased the nice little house and suburb for my mother to retire in.

Last Sunday: that was the day! I was sitting in my cramped little lifestyle, thinking cramped little thoughts, when suddenly the emails lit up green, as notifications began pouring in, one after the other, tripping over themselves in the race to fill up my inbox. "NimbleText purchase!", "NimbleText purchase!", "NimbleText purchase!" Ting! Ting! Ting! A non-stop stream of them. I jumped into the GoogleTM AnalyticsTM to see what was happening. Here was the cause of the whole thing:

"Scott Hanselman's 2014 Ultimate Developer and Power Users Tool List for Windows." Hundreds of pieces of software, catalogued and critiqued. And at the top is a section headed "The Top 10 Life Changing Pieces of Software that Absolutely Every Developer In The World MUST Install, No Questions Asked," or something like that. Number three on the list? My humble offering, NimbleText.

I guess this is how it feels for a book author when Oprah picks up their little tome as "Oprah book of the month". Or when Justin Bieber decides to retweet one of his belieber's, taking them from obscurity to immortality. Albeit a kind of temporary immortality. Hanselman being at once the Microsoft developer's nearest equivalent to Oprah Bieber.

And now, it's the darnedest thing. I can hardly remember what life was like before this. Did I have to waste my own energy deciding which helicopter to take? I couldn't afford people to do things for me at all? Who used to pour my cocktails? I don't even recall! In any case. I'm sure that life is better now.

If the little people are worried that the fame and fortune have gone to my head, they need not worry! NimbleText will still be getting charming features added. I'll make sure it can handle larger numbers, for example, now that my own bank balance requires such a feature.

I have to go now. I just had a reminder from Jeff Atwood. Tomorrow we're going to be driving full-sized remote-controlled Ferrari's off the edge of the Grand Canyon, for a giggle. Why I never discovered this hobby sooner is truly beyond me.

I guess, before I sign off, I should ask my newly appointed scribe to say a warm 'Thank you' to Scott. I am truly honoured!

Read On...

Wed, 27 Nov 2013 11:39:11 GMT

Downtime as a service

I've been working on the direct-sales pitch for my new cloud service.

Step 1 is to find a CIO (recognisable by a hint of 'CIO' undershirt →) and then pepper him with questions, as follows:

—You sir! How much do you pay for downtime?

[CIO looks around]—me?

—Yes, you sir!

—Why, I have no idea.

I take out a calculator. A big one.

—Well, how many servers do you have? A thousand?

—I... I guess so.

—And how often are they down?

—I... don't know!

—Let me hazard a guess: too often! Is that right?

—Why I think it is.

—Then do you know what that means?

—Do I what?

I show him the results on the calculator.

It means you're paying too much!

—I... am?

—Tell me something. When your servers are down, what do your employees do?

—They... they look upset.

—I bet they do. I bet some of them look very upset. And they run around, worrying and flapping about, am I right?

—Yes, that's exactly right!

—And some of them, some of them don't do anything at all do they? When the servers are down they shut down too, right?

—That's right! They sit there. Like fish.

—Fish don't sit, but I've seen it before. Do you know what it means?

—No, no....

—It means they don't know *what* to do! The ones who are sitting like fish. The ones who are flapping their arms. The ones who look upset. All of them are utterly unsure of what they should be doing. They lack the experience. They're out of their depth. They don't have even the slightest clue about what's gone wrong and what the damn hell they ought to do about it. You need to turn to an expert.

—I do! I do need to turn to an expert.

—Well, that's where we come in! We offer Downtime as a Service, look at our specialty downtime data centre!

(I show him a laminated photo of our data centre)

(while he stares at the photo I continue)

—We have a "Five Zeros of Uptime" guarantee. Even Amazon can't keep up.

—Are you sure?

—I'm positive. The Amazons can try, but we beat them almost every day. Try failing over to our hot-swappable server array:

(I show him this)

(He stumbles back a little, he's almost sold)

—Our redundant Dell Storage array has incapacity to spare. We're from the internet. We know things.

And before he can say "boo" I've signed him up to an Enterprise Plan with our no lock-in guarantee (you're still free to get downtime from all your regular vendors) and he's shaking his head and thanking me as he staggers away, a little happier, a little safer, and a whole lot poorer.

That's the plan anyway. Mostly I lose them around the bit where I say "You sir". But maybe next time.

Image of billowing data centre from The fire ate my backup. Flaming computer image found here, but no credit available for the photographer. Charred Dell servers from Rob Smith, here. And see also /dev/null as a Service and S4, the write-only storage provider.
(p.s. I read this out to my six year old daughter and she said "Dad, that does not make any sense at all." Such a kidder.)

Read On...

Sun, 15 Sep 2013 12:50:44 GMT

The Shape of Your Irrationality

Imagine there is a lottery, with a single prize of 1 million dollars.

There are only 100 tickets to this lottery, and, for some unexplained reason, 99 of the tickets have been given to you. Lucky you!

The remaining ticket has been given to someone else, let's call him Jack.

The lottery will be drawn tomorrow. The winner—you or Jack—will walk away with 1 million dollars.

As luck would have it, you bump into Jack. The idea occurs to you that you could buy Jack's ticket and go from a 99% chance of winning to a guaranteed win.

So, how much would you be willing to spend on Jack's ticket? And how much would it take for Jack to part with his ticket?

Standard probability tells us that Jack's ticket has a face value of 1 percent of 1 million dollars, or $10,000.

So if Jack is 'rational' he should be willing to sell it for any value over $10,000. And you should be willing to purchase it for anything less than $10,000. Hence it's unlikely that a trade will occur, as there is no price that is pleasing to both of you.

This isn't a new question. It's a variation on 'the Allais paradox' and two groups of people, psychologists and 'behavioural economists', have been investigating this area practically non-stop for the last sixty years.

Here's what the research predicts in this situation:

Jack is unlikely to part with his ticket for less than 5.5 times its face value. He values it at around $55,000. Optimism in Jack's situation is very high!

Given such an irrational opinion on Jack's part, you should now consider it very unlikely that a trade will take place.

But we haven't looked at the remaining part of the question. How much would you be willing to spend to go from a 99% to 100% chance of winning that million dollars?

You're likely to spend up to 8.8 times the face value of the ticket: up to $88,000. Irrational pessimism on your part is far stronger than Jack's irrational optimism! So there is a chance that a deal will be struck, possibly in the range from $55,000 to $88,000, far higher than the rational price of $10,000.

thinking fast and slow

This and other disquieting aspects of human behaviour are covered in great detail in the book 'Thinking, Fast and Slow' written by Nobel prize winning psychologist, Daniel Kahneman. My wife received a free copy, which she gave to me. Now, thanks to the endowment effect, I would be unwilling to part with it for less than 2.5 times the market price.

(The 'Allais paradox' is covered in Chapter 29, 'The Fourfold Pattern'.)



Read On...

Fri, 06 Sep 2013 11:11:45 GMT

This is why I don't go to nice restaurants any more.

Interior. Restaurant. Customer surveys a large menu.

[Waiter with French accent]—And for you, sir?

[Customer]—A bottle of the '98 Moët.

—I am sorry sir, we are out of the '98 Moët.

—Fine then, the '99.

—I am sorry sir we are completely out of the Moët.

—Cristal then?

—Again sir, my apologies, there is no Cristal.

—Do you have any Champagne at all?

—I am very sorry sir, we have no Champagnes at all.

—Sparkling mineral water then.

—Sorry sir, but...

—Tap water!

—I am sorry sir, the taps are...

—Anything! Do you have anything?

—We have a large forest leaf, which has been left out overnight to capture the condensation from the air, and you are invited to sip the condensed dew drops from the verdant fringe of the leaf.

—Okay, one forest leaf.

—Certainly sir [he begins to walk off] my apologies sir, I have just recalled that we are now entirely out of forest leaves.

—What's left?

—I can only offer you to suckle on the sweaty armpit of a rather tired sous-chef.

—Two of those.

[waiter takes away the menu]

—Sir has made an exquisite choice.

Read On...

Sat, 31 Aug 2013 08:51:11 GMT

A flowchart of what programmers do at work all day

A simple flowchart of what programmers do at work all day:

argh - argh!! -- argh!!!!

I've probably drawn this picture 100 times. In meetings or on the bus, while trying to get started on human or technical problem I don't understand, at times when I'M STUCK.

I was cleaning up today, and took a photo of one copy of it, before I threw it out. I put it on instagram, so I could feel 'done' about it.

Then Jeff Atwood tweeted it and next thing WOW. I can barely get onto my phone for it exploding with news about comments and retweets, from programmers all over the world, who seem to feel exactly the same way a lot of the time.

Thank you ;-)


Read On...

Sat, 31 Aug 2013 00:57:11 GMT

The Telepresent Man.

TL;DR: Hide a short guy under a black sheet, stick an iPad on top, and pay him to go to work in your place.

I have devised a new invention with which I shall revolutionise the workplace, allow tele-commuting to become a societal norm, and thus release us from the stranglehold of fossil-fuelled transportation.

Here's the tag line that will be written on the box when you buy a TPK -- a Telepresent Man Kit:

They say that "80% percent of success is showing up," but if you can't be there in person, you can achieve an estimated 50% of success in life, by sending your Telepresent Man to show up for you.

A TPK consists of a black sheet, two iPads, a game controller and my Patent-Pending USB-Vibrating-Nodule-DeviceTM. In addition to the TPK, you will need to find a short man. He is called 'The Telepresent Man.'

a telepresence device on Big Bang Theory

The Telepresent Man is hidden under the black sheet, and an iPad is attached to the top of his head. He needs to be short enough that the protruding iPad is located at about the height where your own head would be. If you were actually in the office, that is. The iPad is running facetime, connected to your own iPad, which you are watching from home. The Telepresent Man is in your chair, at your desk, attending your meetings. But when your colleagues look at him, what they see is your face, on the iPad.

Unlike conventional telepresence devices (such as the one seen on 'Big Bang Theory' pictured at right), The Telepresent Man can walk up stairs and negotiate uneven terrain.

Here's the bit that's patentable, the PPUVND. This is a small USB powered device attached to the iPad. It has four vibrating nodules that are connected to The Telepresent Man, one on the front of left shoulder, front of right shoulder, and one on each shoulder blade. While the stay-at-home-worker moves a game controller, The Telepresent Man feels a vibration in a corresponding nodule and knows where to move next.

To stop your colleagues from feeling the unpleasant sensation of having a stranger amongst them, watching them work, The Telepresent Man's face is completely hidden. He doesn't need to see at all: the stay-at-home worker does all the seeing for him, and can stop him from running into things by directing his every move.

Larry the surrogate in arrested development

When I presented this idea to my board of trusted advisors, one of them pointed out that almost the exact same idea was used on the television show 'Arrested Development.' A character called George employs a 'Professional Surrogate', Larry, to represent him at family meetings. From what I've read, my idea is completely different. And in unrelated news, Richard Mason has been let go from my board of trusted advisors. And for your information, Richard, Nobody wants to hear about Arrested Development all day.


Read On...

Wed, 28 Aug 2013 08:51:59 GMT

Interview with an Ex-Microsoftie.

—So, you used to work at Microsoft?

—Yep sure. I used to come up with names for all the special folders.

—The special folder names in Windows?


—"Program Files", is that one of yours?

—Sure is. I thought, "This is where we'll put the programs. On the file system. And since they're gonna be made out of files, I'll stick the word "Files" on the end. With a space in the middle. People are going to be typing this all the time, so they'll want it to be as long and descriptive as possible."

—And what about System32 is that yours?

—Yep. I thought, "these files are 32 bit files. So I'll put them here."

—And that was pretty successful?

—Yes. I did such a good job naming it System32, that nowadays it contains all the 64 bit files as well.

—Then what happens to the 32 bit version of the 64 bit files. Where do they go?

—Well they can't go in System32, because on a 64 bit machine, System32 is where the 64 bit files go. So if we're running a 32 bit executable we lie to the executable and tell it that "System32" points at another folder, called SysWOW64 and that's where we stick the 32 bit files.

—Why is there a 'WOW' in the middle of the name?

—I was typing System64 and half way through I just thought: "WOW, nature is beautiful!"

—And the 32 bit files, they go in SysWOW64, since the 64 bit files are in System32?

—Yep. (Laughing) Oh I took a lot of meth that day, my friend.

—And how about the "users" folder. That's quite succinct, is that one of yours?

—Oh no, that's after my time. I was there for the previous one: "Document and settings."

—Surely you regret that name. It's clearly too long?

—Too long!? It's too short. Do you realize you can put anything in there, not just documents and settings? I wanted to call it "Documents and settings and ideas and lists and notes and string and ponies and candy and pieces of fluff and temporary internet files and stuff". I got into a fist fight with Ray Chen over it and I only let him have his way when Steve Ballmer sat on me.

—And you're retired now?

—I am now. (He takes a long swig from a bottle of whiskey. The brown fluid gurgles as it rushes down the neck of the bottle.) At one time I tried to get a job on the team that comes up with version names.

—You missed out?

—Not drunk enough. Not even close.

Read On...

Mon, 26 Aug 2013 11:37:05 GMT

CRUMBS! Commandline navigation tool for Powershell

Penfold from Dangermouse and the word Crumbs!

I live on the commandline as much as possible (which is not nearly enough) and hence spend a lot of time navigating from one place to another. But, as much time as I spend navigating, I spend considerably more time thinking about ways to improve it.

One tool I've come up with is a set of functions that I call:


* Pronounced "CRUMBS!" in the voice of Penfold from Dangermouse. (I realize that my American readers are probably unfamiliar with concepts like "Penfold" and "Dangermouse" so I'll give you a few minutes to look up those concepts, watch a few episodes on the YouTube, learn about The Goodies while you're there, etc.)

download crumbs.ps1 (dot it)

crumbs at github

To use it, download it, open powershell and 'dot' the file, i.e. execute: ". .\crumbs.ps1"

Crumbs consists of two functions: crumb and crumbs. It borrows a metaphor from the story of Hansel and Gretel. You may recall that they dropped breadcrumbs in order to find their way back. Although in this case the breadcrumbs are more like transwarp teleportation wormholes that let you zing across space and time. And there's no birds that eat the crumbs nor are there any gingerbread houses or cannibalistic witches. But I digress.

Here's how you use the two functions.

Let us say that you're in some deeply nested folder which you might want to get back to. Use the crumb command to drop a crumb:

PS C:\Work\Scratch\Pyjamas\Carousel Fandango\Rhubarb\> crumb

There. You dropped a crumb and now you'll be able to get back to that location. Let's go somewhere else...

PS C:\Work\Scratch\Pyjamas\Carousel Fandango\Rhubarb\> cd C:\Play\Games
PS C:\Play\Games> crumbs
0 -> C:\Work\Scratch\Pyjamas\Carousel Fandango\Rhubarb
PS C:\Play\Games> crumb
PS C:\Play\Games> crumbs
0 -> C:\Work\Scratch\Pyjamas\Carousel Fandango\Rhubarb
1 -> C:\Play\Games

Did you see that? When we called the crumbs command, it listed allllll of our crumbs... (we happened to only have one crumb) and it said that the id for that crumb was number zero. Then we added another crumb and saw it was number 1 in the list of crumbs.

Now if we type "crumb 0" we'll jump straight back to that location...

PS C:\Play\Games> crumb 0
PS C:\Work\Scratch\Pyjamas\Carousel Fandango\Rhubarb\> 

That's pretty much it. You can drop as many crumbs as you like... well up to int.max of them I guess. And you can remove them by "minusing" them away, like so:

PS C:\Play\Games> crumb -0

(Crumb 0 deleted)

Crumbs only live for the duration of your console session. I had an idea about making a 'bake' command that would make a crumb permanent (by turning it into a 'crouton') -- but either the metaphor was stretched too far or I got hungry and went off to eat. Whatever the cause, I never got as far as the bake command.

Included in the script above are aliases, that let you type 'cr' instead of 'crumb' and 'crs' instead of 'crumbs'.

And while you're at it, go buy a Penfold 'CRUMBS!' sticker, as seen above.

Navigation in Other Worlds

Meanwhile, in the bash world they have some very cool tools to make navigating easier. In particular several tools such as autojump, z, v and fasd use the concept of 'frecency' (the combination of frequency and recency) combined with auto-completion to let you find your most likely next location in as few keystrokes as possible. Are there equivalents in Powershell? Seen one? Got one? I've just found "Jump-location" and plan to give it a spin.

Also, in the last few days I came across an approach that is not too different to crumbs Mark and Jump. There was a lengthy related discussion at hacker news.

I've implemented my own version of this as well.

download markjump.ps1 (dot it)

markjump at github

In this case there are four functions: Mark, Jump, Unmark and Marks.

With 'mark' (unlike crumb) you specify a friendly name for the current location. Then with Jump {name} you go back to it. Use marks to list all the names and locations you've marked. And with unmark {name} you can remove one from the list. (Go read the readme if you really care.)

It includes aliases 'm' for mark, 'j' for jump, and um for unmark. You might want to comment those out if they collide with other aliases you use.

Crumbs is useful for adhoc navigation tasks. Marks is useful for links you use often. (It persists across your sessions). Both are useful. Both are a bit raw. Feedback welcome.

Read On...

Fri, 26 Jul 2013 23:49:22 GMT

Little tool for making Amazon affiliate links

enter your affiliate id and a url at amazon, and get back an affiliated url for that product

This is a very very very very little tool. You give it your Amazon affiliate id, and any Amazon url for a product, and it gives you back a url for that product, with your affiliate id.

amazon affiliate link maker →

There used to be a lot of neat little tools like this around the place, in the days when people controlled the branding of their own blogs (one bazillion years ago), but I could no longer find one I liked, so I built this one. It uses code that is a part of You Must Get It. If you are signed in to You Must Get It, then it will enter your affiliate id for you.

There's also a version for bulk conversion of urls. Combine this with NimbleText and you have a way to turn plain lists of amazon urls into large swathes of affiliated html. If that's your thing.

Read On...

Fri, 19 Jul 2013 11:42:38 GMT

Extracting a Trello board as markdown

(or "web scraping from the chrome console, with jquery")

Assuming you use Trello and the Chrome browser, here's a technique for extracting a trello board onto your clipboard as plain text.

Navigate to the Trello board you want to grab, and bring up the chrome developer tools ([F12], or [Ctrl]+[Shift]+[I], or Tools → Developer Tools)

Go to the console (chrome console icon is a greater than followed by an equivalence indicator) -- and enter this piece of javascript. (Don't read it.... just enter it... trust me).

var s = [];var x;s.push("# " + $("#board-header").children()[0].innerText); $(".list:has(.list-title)").each(function() { x = this.innerHTML; s.push("## " + $(this).find(".list-title")[0].innerText);$(this).find(".list-card-title").each(function() { s.push("* " + this.innerText); }); }); copy(s.join("\n"));

Okay -- spaced out over a couple of lines it reads:

var s = [];
s.push("# " + $("#board-header").children()[0].innerText); 
$(".list:has(.list-title)").each(function() { 
    s.push("## " + $(this).find(".list-title")[0].innerText);
    $(this).find(".list-card-title").each(function() { 
        s.push("* " + this.innerText);

The whole trello board will now be on your clipboard, in nature's favorite format: markdown.

Use the intrinsic 'copy' function to copy a value to the clipboard

One lesson I learnt while putting this together: you can use copy in the console to put a value onto the clipboard. This doesn't work in regular pages, for security reasons.

Inject jQuery into a page

If you want to use this kind of data-extraction technique on a page that doesn't have jQuery, then you'll want a simple technique for injecting jQuery into a page.

Just pop down to the console and paste this:

var script = document.createElement("script");
script.src = "";

jQuery will now be available on that page, and you can sizzle to your heart's content.


  1. You may first want to make sure jquery isn't already loaded.
  2. And you have to make sure the 'script' variable doesn't overwrite any existing variable of the same name.
  3. You may want a specific jQuery version.
  4. Use at your own risk, no warranty or replacement for lost limbs etc.

Read On...

Wed, 10 Jul 2013 12:35:30 GMT

hgs: Manage Lots of Mercurial Projects Simultaneously

hgs is a simple set of powershell functions that let you find and manage multiple mercurial projects -- simultaneously.



A friend of mine creates way too many mercurial repositories. Where other people would have multiple projects in one solution, he has numerous individual projects each in their own repository (which are sometimes shared back into each other via nuget packages).

The result is a very explicit separation of concerns, but also a *lot* of repositories. Just trying to get all of his changes involves pulling from many different repositories.

This gave me the motivation I need to come up with a simpler way to manage multiple repositories.

At first I decided to make a windows app that showed all your repositories at once, and let you select many of them to run a command against simultaneously. Here's the basic layout I was thinking of:

a window for entering commands, a checkedlist box for selecting repositories and a textbox for displaying results

The clever part is that the result of any command would be parsed by a series of regular expressions that are used for determining the status of each repository, relative to that command. Thus you can see each repo light up as green, when your multiple pulls suceed, or red when your multiple updates fail, etc. And a lot of effort would be spent on having first-class keyboard support, so your mouse is free to gather dust.

To get this working would've taken many bus-rides to do the way I wanted, and a lot longer to maintain and improve it.

Fuck that.

Instead I wrote three lines of powershell, and got the same result.

Introducing hgs -- the plural of hg.


To get started the .ps1 file above. Then, from powershell, dot-source the file to install the three functions. (Oh, read it first if you must.)

hgs is composed of three simple functions. Here it is in its entirety:

# function hgs_update  --  updates/refreshes "hgs.txt"
new-item -path function:hgs_update -value { dir . .hg -recurse | % { $_.Parent.FullName } > $env:localappdata"\hgs.txt" }

# function hgs_ls      --  list the contents of hgs.txt 
new-item -path function:hgs_ls -value { get-content $env:localappdata"\hgs.txt" }

#function hgs          --  runs hg commands against all folders in hgs
# usage: hgs {commands},  examples: hgs stat, hgs in, hgs fetch 
set-item -path function:hgs -value { $a = $args; $color = $host.UI.RawUI.ForegroundColor; type $env:localappdata"\hgs.txt" | % { pushd $_; $host.UI.RawUI.ForegroundColor ="White"; "Results for: " + $_ + ":"; $host.UI.RawUI.ForegroundColor =$color ; hg $a; popd } }

All three functions are concerned with a file called 'hgs.txt' a file containing a lists of all your mercurial repositories.


To update the hgs.txt file, call the function 'hgs_update'.

This function pipes the name of every folder which contains a folder named '.hg' into hgs.txt (in other words, it searches for all your mercurial repos).


The second function, hgs_ls gives you a peak at the content of hgs.txt (i.e. it shows you all the mercurial repos that were found).


The third function, hgs lets you run a hg command against all the repositories at once.

For example you might try:

hgs stat    # check the status of all your repositories
hgs in      # show new changesets for all your repositories
hgs diff    # diff all your repositories
hgs pull -u # pull from all remote repositories and update if changes were found
hgs fetch   # pull changes from all remote repositories, merge new changes if needed. 
            # (requires the unloved  fetch extension)

I provide those examples because they are all things that you might do 'en masse'.

Other commands like revert, forget and definitely push should be done on a more careful case-by-case basis.

And powershell's wonderful code completion feature means that you only have to remember hgs (the plural of hg) and you can tab through all three functions.

Best of luck.

Read On...

Sat, 06 Jul 2013 08:18:23 GMT

You Must Get It!

It's been many months since I made my rash decision to purchase '' and in that time I've worked tirelessly to establish the 'you must get' empire.

It's now ready for you to use and enjoy, at an even better url than before:


You Must Get It is a place where you can show off the products you love, and see what other people are recommending.

Here's your six step plan to consumer bliss:

  1. Go here: YouMustGet.It
  2. Sign up!
  3. Follow some interesting users. Or follow me.
  4. Drag the 'favelet' into your bookmarks bar. (You may need to show your bookmarks bar first)
  5. Travel around the internet, finding all the products you love, and recommend them all, by clicking the 'must get' favelet
  6. Tell all your lucky lucky friends!

Get Rich By Being Greedy

Death to capitalist pigs, three cheers for Full Communism Now and all that -- but check out this feature that lets *you* rake in the affiliate dollars.

You can specify your Amazon affiliate ID in your user profile. Thereafter, any time you recommend a product at Amazon, we will use your affiliate ID. No matter what Amazon product link you provide we'll turn it into an affiliate link using your affilite ID.

At some sites (cough - pinterest - cough) they do something much nastier: they always use their affiliate ID for all Amazon links. In fact, even if you've already explicitly specified an affiliate ID they take your ID out and put theirs in! We don't do that.

Feeling Lazy?

And, there's one other feature that I quite like: the 'Feeling Lazy' button.

Too lazy to click around looking for things to buy? Click the Feeling Lazy button and you'll be taken to a new random product every 3 seconds.

(I also plan to add the 'Feeling Rich and Lazy' button, which will take you to random products, and randomly buy a few of them as it goes.)

So join you must get it today. Get involved. Be awesome.

Great products: Where are they?

Apart from scouring through every product at a site like Amazon, Ebay or Etsy, you can find some excellent curated lists at these sites:

Embed your own...

Also, you can embed a YouMustGetIt list of your own product recommendations by using these three lines of code:

<ul id="umg_list"></ul>
<script type="text/javascript" src="http://YouMustGet.It/scripts/embed.js"></script>
<script type="text/javascript" src="http://YouMustGet.It/API/said/secretGeek/10?callback=umg_callback"></script>

(Substitute your own username in, and how many posts you want to see, in place of 'secretGeek' and '10' respectively)

The embedded stuff is still a work in progress, but should improve in the next few days.

Read On...

Sat, 15 Jun 2013 12:56:21 GMT

AddDays: A Very Simple Date Calculator

Add days windows app, specify date, number of days to add, and a format

To help my business manager (aka wife) with invoice preparation I wrote a very simple date addition calculator.

You can download it here.


Given a date, it adds a number of days to it, so you can calculate due dates for invoices.

When I told my colleagues about this they each had different but equally 'helpful' alternatives I could have used.

  1. Why not user powershell? (Get-Date).AddDays(50) | clip
  2. What about the built in "Date Calculation" mode in Calculator? (The templates feature of Windows 7 Calculator is pretty interesting by the way)
  3. Why not just use excel?
  4. Why not use the DATEADD function in SQL? Most people have SQL Management Studio open all the time, don't they?
  5. Why don't you use Invoice Place?

I like writing my own software, and the little details are the things I love the best. The moment you change the date, or change the number of days to add, or change the format, the result is immediately copied to the clipboard.

Anyway, if it helps you so be it. No support it offered, and of course I disclaim all responsibility to the best of my ability.

Writing your own solutions to your own problems is very satisfying.

Regarding the special features of 'calc.exe', here's a screenshot of calc in 'Date Calculation' mode (available in Windows 7 and above)

Read On...

Tue, 11 Jun 2013 12:54:02 GMT

Google caught in a lie.

In the wake of the PRISM hacking scandal, we're all looking at the Big Cloud providers with a slightly more cynical eye than ever before.

So when I noticed a few pieces of intellectual dishonesty at Google Analytics I dug a little deeper than I normally would. And the deeper I dug, the worst things got. Hold on for a, well not a wild ride, more of a gentle somewhat nerdy ride, with a little trash-talking of Google+ along the way.

On the login page for Google analytics, they show you some enticing info-porn to get you excited before logging on.

Something fishy about this pie chart immediately caught my eye:

Look at the largest section of the pie, that blue section.

No way is that 34%! It's clearly just over 25% -- what kind of dumb mock up is this? Are they demonstrating their awesome analytic platform by showing us some faulty analysis?

But then I did a coffee spit.

The pie chart is suggesting that the two biggest contributors to your social traffic will be people 'plus-oneing' your content with Google+ (blue), and people re-sharing your content, with Google plus (light blue). In your dreams, Google! Your sad, sad, lonely, social-misfit dreams.

So, I crunched the numbers to see if the percentages of the labels had been tampered with, or the pie itself was altered. Here's the chart I produced, using the same raw numbers:

Some more bugs in their image. I'll do these quick fire in an ordered list:

  1. The table header says "1-7 of 7", when there are clearly only "5". Counting is hard, poor Google.
  2. Didn't 'Read it later' change its name to 'Pocket' about a million years ago in internet time?
  3. What is 'delicious'? Some ancient link-sharing site my grand-dad used on AOL from his fax machine?
  4. And are they incapable of recognising the possibility of traffic from twitter, or just incapable of saying the word?

So it's pretty obvious by now that the marketing image is very much a contrived image. But does it have any resemblance to the produce itself?

Here's a real pie chart from the dubious social network feature of Google Analytics: (I've removed my dismal figures)

As I suspected, and unlike the mockup, the portions are laid out clock-wise, descending, starting at the top. And the percentage's are drawn inside the pie, not outside of it.

And this time you can tell you're looking at a real Google Analytics pie chart, because Google+ contributes less than 1% of the social traffic.

Read On...

Thu, 23 May 2013 10:58:40 GMT

NimbleText 2.0: More Than Twice The Price!

The latest release of NimbleText is a major milestone, took a lot of work, many bus trips.

As a user of the product, I feel it's good now. I don't want to say it's complete -- because I know how big the backlog still is -- but there's a sort of completeness to it. If no more features were added for a while, I think that would be okay.

I added custom sorting features, and auto preview, and more documentation, and a bunch of other stuff.

I even wrote one of those feature checklists you see in all the expensive professional software suites. --->

Now that's pretty bloody serious stuff.

But then I did something really serious:

I more than doubled the price.

Everywhere I looked, people were telling me to put up the price.

This article crossed my desk today: An eBook pricing model that resulted in $100,000 in sales and contains this quote:

I consulted Patrick McKenzie. Can you guess what he said?

"Charge more."

Of course Patrick would say that.

But when I stumbled onto this article, also just today, 'four pricing principles to never forget' -- the following ALL CAPS headline was like a slap across the face:


That was it! Enough was enough. I shut the browser! Slam! Opened the html editor! Whoosh! A search, a replace-all, and it was done in less than a minute.

The price went from $9.95 to $19.95. Double! DOUBLE! Plus five cents!

And I don't regret it for a second. At $20 it's still a steal. I'm seriously thinking of going to $50. Who knows where this madness will end? $75? $78.50?

I have unleashed a pricing monster!

Further reading:

  1. Product Pricing Primer -- Eric Sink.
  2. Money Buys Happiness and You Can Never Have Too Much, New Research Says

Oh, and you'd be wise to get in on TimeSnapper before this pricing madness spreads.

Read On...

Mon, 06 May 2013 12:46:15 GMT

A Computer Simulation of Creative Work, or 'How To Get Nothing Done'

Every year is getting shorter, never seem to find the time
Plans that either come to naught or half a page of scribbled lines

According to the available data, I'm a hard-working and creative person. Yet my productive output tends to hover just above nil. My feelings are generally in line with Roger Water's lyric, quoted above. Why? What causes the gap between work and productivity? But more importantly: can a computer simulation shed light on the underlying problem?

I set about modelling my personal productivity, with javascript and flot.

Here's how the model works:

Every bus trip I work and work and work, always on what is the most pertinent task for the project I am working on.

But as I work, I sometimes think of new projects. I immediately (and at no cost) add those projects to my backlog, then continue with my current task.

As soon as I finish a task, I look over my set of all next actions and choose whichever one feels most interesting at that point in time (modelled as a random selection)

You can play with this simulation yourself:

Creative Dilligence Simulator

The parameters are configurable. By default each project contains 10 tasks (these are mini-projects really). And each time I do a task there is a 25% chance I'll think of a new project.

The results of the simulation are woeful!

Here's an example:

After a year of bus trips, I've done enough hard work that I could've completed 20 projects. Instead I've only finished only 2 (emphasized by the green arrow). Re-running it, I sometimes complete as many as 3 or as little as 0. Meanwhile my backlog of work is big enough to keep me busy for years to come.

As simplistic as the model is, it already makes me feel uncomfortable with its home truths. I know this feeling all too well. Hard work, but it's like spinning your wheels while stuck in mud. I know that my time is spent always on tasks I consider worthwhile, yet I'm still getting nothing done.

Here's the shocking thing. This low productivity is not caused by all the usual culprits we list when discussing 'procrastination'. This isn't because of low motivation or excessive distraction. This isn't because of fear (the alleged mind killer) -- it's not fear of shipping, fear of criticism, fear of success, or any other paralysing phobia.

Getting 'Things' Done versus Getting 'Projects' Done

This is the difference between utilization and productivity. High utilization can be just busy work.

This is purely organisational pathology, and 100% curable.

The immediate question is what to do about it. Now the modelling becomes fun.

If I can decrease my ability to think of new projects, down to around 10 percent (approximately 1 new project idea for 10 tasks done), then I manage to ship more projects.

At the end of the year I've now completed between 8 and 20 projects. Yay. But now a new problem arises: I frequently run out of work to do. Many bus trips I just sit there, twiddling my thumbs, staring out the window. For me, that's a terrifying prospect, a sort of waking death. But in any case, I think it's outside my control. This continual thinking up of new projects (albeit stupid STUPID projects) is just a fact of life. You might as well ask a cat to stop following a laser pointer.

The trick instead is to come up with a new strategy for picking tasks. When I finish one task and it's time to move onto another, I need to be far more careful about which task I work on next.

So I implemented a strategy called 'stick to a project'. In this strategy, I keep working on my current project until that project is done. The results are much more satisfying. I still end up with a giant backlog of work -- but the amount of projects that I've shipped is now exactly in line with the effort I've put in.

That's all I needed to get out of the model -- and at this point I can stop modelling and return to doing.

But it's also just the tip of what the model shows you. Different people have different fears and different desires. Depending on your personal preferences different results are optimal. You might be driven by any of these:

  • Fear of drowning in work (minimize backlog)
  • Fear of running out of work (maximize backlog)
  • Love of a big backlog (maximize backlog)
  • Hate working on the same thing all the time (continual switching)
  • Fear of negative feedback after releasing work (minimize project completion)
  • Desire to release work constantly (maximize project completion)

Play with the numbers, you'll see how to get what you want. Or copy the code and change the model to reflect your own behaviour.

That link again:

Creative Dilligence Simulator

Models are not reality

In practice, things get a lot messier. Projects have variable sizes. Projects grow as you work on them. Some projects *should* be abandoned, not stuck to. (If a job's not worth doing, it's not worth doing properly).

The model is very simple but it was complex enough to demonstrate something useful to me, so I'm happy to publish this as is.

Now I must get back to the gormless and unstoppable implementation of whatever addle-brained scheme has floated to the top of my steaming heap of incomplete mini-projects. Wish me well.

Read On...

Sat, 20 Apr 2013 00:47:27 GMT

NimbleText 1.9 -- BoomTown!

I put out a new NimbleText a few days ago.

The release notes are here, but do you want the minutely-detailed and wildly self-indulgent story behind the release notes? Of course you do!

Along with a spattering of smaller improvements, the main innovation is that you can now expose your settings (and quickly change them) from the toolbar.

I wanted this for a while, but couldn't find the right way to let the user configure it. Finally, with inspiration from Windows 7, I came up with using a pin/unpin metaphor, inside the Options form, like so:

Coming up with this design was surprisingly difficult. Some of the designs I rejected were:

Some people asked for a "view" menu where you check or uncheck the options you want to have appear on the toolbar. Here's a quick mockup:

This concept was broken for two reasons.

First, it looks like you're turning the option itself on or off -- not turning on whether or not the option is shown in the toolbar.

Second, if you were to click one of those menu items, thus toggling its checked state, this would also have the undesirable side effect of closing the menu. So if you wanted to show or hide three settings you'd need to re-open the menu three times, for a total of six-clicks. Annoying behavior! (Incidentally my NextAction tool suffers this problem, embedding so many settings in deeply-nested context menus that collapse whenever you click them. Overriding this behaviour is problematic!)

So the new plan was to put checkboxes of some sort inside the Options form, adjacent to each option. But take a look at this mockup:

Again it's easy to think that clicking the new checkbox will cause the option to be turned on. I wasn't going to implement this or anything like it. Then I noticed the way application icon pinning works in Windows, from 7 onwards.

It's an elegant solution, maybe the nicest touch in Windows since they shot the dog.

So I had my big-chief-graphic-design-intern (i.e. Me) whip out a dodgy mockup, ran it over to my main opinion-deflection-test-subject (i.e. Rhys) and after a few short bursts of shouting the project was green-lighted and implementation began.

Here's the mockup with which I got approval from the board:

If it seems weird to agonize over a small feature like this, I could point out not only a long history of such behavior from myself, but also I can provide evidence that i'm a bit of a toolbar fetishist, having written 6 articles on the topic previously:

What UX have you agonised over lately?

Read On...

Mon, 15 Apr 2013 10:39:23 GMT

Line Endings.

3 people arguing over line endings.

I had a lengthy article here -- browsers, typewriters, javascript blah blah blah, cultural tolerance to backward incompatability in Mac and Microsoft worlds, blah blah blah -- but really, the Hanselman pretty much beat me to it, and all I've got left is a cartoon.

((As a derivative of a GPL'd work ("Tabs."|"Spaces."|"Both."),) The above image is licensed to you under version 2 of the GNU General Public License.)

Read On...

Sat, 16 Mar 2013 00:24:49 GMT

**This** is how you pivot

Startups love to talk about 'Pivoting' -- those sudden changes in strategy, right angle turns that take you from obscurity to success.

"Burbn" pivoted from a location-checkin app to a stylized photo sharing app and became billion-dollar company, Instagram!

Doug and Dinsdale Piranha

But to find the masters of pivoting, we need look no further than the monty python sketch, the piranha brothers. This is pivoting done *right*!

At the age of fifteen Doug and Dinsdale started attending the Ernest Pythagoras Primary School in Clerkenwell. When the Piranhas left school they were called up but were found by an Army Board to be too unstable even for National Service. Denied the opportunity to use their talents in the service of their country, they began to operate what they called 'The Operation'. They would select a victim and then threaten to beat him up if he paid the so-called protection money.

This must not have been a particularly succesful strategem, for we are about to learn that the Piranha Brothers chose to 'pivot'.

Four months later they started another operation which the called 'The Other Operation'. In this racket they selected another victim and threatened not to beat him up if he didn't pay them.

This strategy also met with limited success and another pivot was in order.

One month later they hit upon 'The Other Other Operation'. In this the victim was threatened that if he didn't pay them, they would beat him up.

This for the Piranha brothers was the turning point.

Read On...

Thu, 07 Mar 2013 10:52:31 GMT

Art of the command-line helper

The scariest code I ever wrote is the dialog in NimbleText that helps you use the command-line.

Much smack has been written in the past about confusing command-line helpers in other apps, so I set out to build this dialog with great trepidation in my heart.

Joseph Cooney has laid into two particular apps, a gui for wget, and a gui for robocopy. Even Jeff Atwood had a stab at wGetGui.

Here's what they looked like:

gui for wGet gui for robocopy

And here's a typical user response upon first encountering such a command-line helper:

I downloaded both these apps and tried them out.

Okay, the kindest thing you can say is that they are comprehensive, and with their use of tooltip text they do offer a little more help than the screenshots would suggest.

But they still give an immediate slap in the face to the end user. Something I want to steer away from.

So command-line helpers are a challenge. And to increase the pressure a little more: the command-line feature in NimbleText is only unlocked if you buy a license. If I'm expecting this feature to be worth money, they I really have to not screw it up.

What I did.

The first thing was to use descriptive labels, instead of verbatim option names. Instead of having a checkbox named "--rawdata" I'd have a label that said "Raw data". While this is only marginally more readable, it hopefully decreases the effect shown above.

Next I added a textbox at the foot of the form, where the command-line you've created is written, live, so you can see the output of your furious clicking.

There's a button for save, so you can save your command-line straight to a batch file. (It works from powershell too). A copy button, to put the command-line into your clipboard, and an execute button, which launches a cmd.exe process, and tries out the command-line immediately.

Other than that, I just sweated the small stuff. Alignment, spacing, capitalization, tab order, tool tips, everything as consistent as possible.

What I probably failed to do was give The Dialog any breathing space.

(And looking at the screenshot now I see a slight inconsistency with spacing, which should be fixed by the time you look at the application itself.)

Here's what I came up with:

Any suggested improvements? Please send them in.

Read On...

Thu, 28 Feb 2013 10:57:34 GMT

Go and read a book.

I tweeted this yesterday, but wanted to discuss it in a little more than 140 chars

"Reading a book" is a classic important but non-urgent task. When your lifestyle lacks any book time, you know you're in the wrong quadrant.

Merril Covey Matrix

This is a reference to the four quadrants matrix (urgency versus importance) from the book 'First Things First' by Stephen Covey et al.

The idea is that many of the things we do can be ranked as either important or unimportant, and as urgent or non-urgent.

It's a neat and enlightening concept, but there's something utterly impractical about it.

A response from Dan Puzey summed it up well:

The real problem is that "organizing my life into quadrants" always seems a non-important non-urgent task...

Maybe that's why I've always felt uneasy about the four quadrants idea.

Don't spend time categorizing everything into one quadrant or the other. Don't get caught up in grandiose and abstract questions like "Do I have my life values in order? Am I doing first things first every day?"

Just ask yourself the simple, practical question "Have I read any good1 books lately?"

Your answer sums up a hell of a lot about how you're life is going. If you find you're not reading any good books, then you know right away that your life is out of balance.

Now stop staring at your navel, and go read Slaughterhouse-Five.

  1. If all you've read lately are comic books, by the way, then the answer to the question is an emphatic 'No'.

Image from Wikipedia: Merrill Covey Matrix

Bonus unrelated wikipedia link: Four-Quadrant movie.

Read On...

Sun, 24 Feb 2013 11:35:41 GMT

Slurp up mega-traffic by writing scalable, timeless search-bait

In which I follow the advice of Patrick McKenzie to try and get my little software products into the eyeballs of a whole new audience.

sunday night blues, micro-Isv style

So, it was one of those lazy Sunday evenings when a microIsv guy does what he does best: he looks through the Google Analytics of his products, desperately trying to work out why he is not yet a millionaire, desperately trying to find what tiny tweak he can apply that will ensure he has no need to head to work in the morning, or ever again. (This is known as 'Sunday evening blues, microIsv-style')

When I looked at the search traffic for both sites (TimeSnapper and NextAction), something leapt out at me, the way a tiger in the wilds of India might jump out at a plump looking passerby.

The only search terms people were using to find TimeSnapper were terms like "TimeSnapper", "Time Snapper" or related mis-spellings of the product name.

Noticeably absent from the keyword traffic was every single person in the world who hadn't already heard of the product from some other source. No one looking for "I just lost all my work, how do I get it back?" or "How do I make timesheets easier?" or "How can I understand my own bad habits?" or "Continuous Screenshot Taking" and so on for a million other search terms. (Hint: I just demonstrated the SEO technique of google-bombing oneself ;-) ). So my website -- That Dilligent Little 24 Hours a Day 7 Days a Week Sales Guy, wasn't drumming up one iota of new sales.

And the same for NimbleText. A tiny trickle of people would turn up, but only via search terms like "NimbleText", "Nimble Text" or "World's Simplest Code Generator" (the product's original name) -- and no one else.

So I asked myself, as I sat there on that uneventful Sunday eve: How do I make it happen?

In times like this, I always turn to the writings of Patrick Mckenzie (aka Patio11 on twitter and Hacker News). For SEO he recommends writing 'evergreen' and 'scalable' content.

'Evergreen' content is timeless content: stuff that isn't dependent on today's news cycle or the latest fashion.

'Scalable' content is the sort of content you can write a lot of. The sort of guff that doesn't take a great deal of soul searching.

In relation to NimbleText I easily came up with a basic idea for 'scalable' content generation. Normally, when writing about NimbleText I think about the features, and there's a finite amount I can write. If instead I were to write a short article on every possible specific situation where NimbleText could be used, then you'd be looking at a limitless source of article topics. Think of every type of code it can generate, every example piece of HTML it can produce, every piece of SQL it can concoct, you would be looking at an endless stream of simple, albeit quite repetitive articles. You could churn out such articles at a pretty fast rate. (NimbleText itself could even help with this task.)

Articles such as 'How do I generate insert statements?' may not be the sort of thing that sets the world on fire -- they're never going to attract a viral influx of rabid fans -- but hopefully they'll pander to some fine strange of the long tail of search traffic, and, over time, bring in a trickle of fresh visitors, potential paying customers.

This strategy is a sure winner from an SEO point of view. Wikipedia is essentially nothing but a giant engine built for the creation of Scalable Evergreen content. No wonder it takes first place for just about any search you perform.

So here's the short list of NimbleText-related articles I've written on the bus, since coming up with this strategy:

SQL Master Class (for NimbleText)

It takes less than one bus ride to write such an article, and they're only getting easier. I've got a backlog of thirty such topics and I'm sure with a more concentrated effort I could grow this to many more. Is it worth it? I'm unconvinced, but I'll look at the analytics over time and see what happens.

I've been running this experiment for a few weeks now. Already i've started to see people arrive from new search queries, suited to the articles I've written. The volumes are hardly mega, but the littlest steps bring the most satisfaction.

Read On...

Fri, 22 Feb 2013 22:46:50 GMT

Do *NOT* try this Hacking Script at home

From this answer at stackoverflow, I read:

I saw this one in a bollywood movie. Our hero was busy romancing with his gf until his friend informs him about upcoming college exams. So, he decides to get examination papers by hacking into his college network. This is how he goes about it:

Enters Lab. Opens up a command prompt window. Types - Hack System

And that's it!!...A window pops up- System Hacked

He gets access to all papers and returns to his gf for a romantic song :)

Mind blown. I just had to try it out:

C:\temp>copy con hack.bat
@echo %* hacked!!!!
        1 file(s) copied.

C:\temp>hack system
system hacked!!!!

C:\temp>hack internet
internet hacked!!!!

C:\temp>hack FBI
FBI hacked!!!!

Drunk with power, yet trembling in terror; I'm sitting here with the door barricaded, certain the feds are going to burst through the door at any moment.

Do *not* try this at home.

Read On...

Thu, 07 Feb 2013 10:19:17 GMT

The 'Should I automate it?' Calculator

Should I automate it?

Here's a clever calculator that let's you answer the age-old question: "is this thing worth automating?"

I put this together a few days ago and I just keep needing to use it! Situations keep coming up where I'm gobsmacked to find that our 'gut-feel' about the relative merits of two approaches is just not borne out by the simplest back-of-the-napkin calculation.

The neat thing about this calculator is that it distills the choice down to its most crucial elements, so you can come up with an answer very quickly.

Once you've plugged in some values and gotten your answer, you can easily share it with those chumps in management or with a clever colleague -- click the 'Save this result' button, and you'll be given a url that you can send around, preserving all the values you plugged in, allowing others to tinker with your calculation and verify everything for themselves. (Implementing that bit was the funnest of the fun. Remind me to show you the 'GetHashyCode' extension method.)

When you take a moment to play with the figures, there's a bunch of things that leap out at you.

First up -- this rather obvious result:

"If you're only going to do it once, it's not worth automating."

That might be quite a shock to some of my automation-happy friends, but I'm afraid the result is unequivocal.

Second: it's amazing how much value you can add by automating something that happens a lot.

Imagine your company has a timesheeting system that takes 10 minutes longer to complete than it should. It's used every week by 20 people, so in the next 2 years it will be filled out approximately 2000 times. You work out a way to save those 10 minutes.... how much effort should you put into making this improvement? Should you bail out if you can't fix it in 1 day? 2 days? 3 days? Here are the figures. It turns out the break even point is 430 hours of work -- around 11 weeks! So yes, if it's going to cost you a whole day of work to improve the timesheeting system -- go ahead and do it! You'd be insane not to!

Jan Ernst Matzeliger (1852  1889) Inventor and Businessman

Of course, the benefits of automation are more than just the time it can save. When a task becomes free to do it changes the nature of the value proposition. Read about the amazing impact of Jan Ernest Matzelinger -- a brilliant automator who revolutionised the shoe industry.

The calculator could be simpler, or it could be more complex.

A simpler version would remove the 'hourly rate' fields -- so the answer would be in just hours.

A slightly more complex version would allow there to be a different hourly rate for the person who cleans up when manual work goes wrong. This is realistic. Clean up crews can be expensive. Also the costs of maintaining the automation could be factored in. Cheap automation solutions tend to be very brittle.

Okay -- I'm all out of discussion about this little tool. Use it, share it, automate something today.


Read On...

Sat, 19 Jan 2013 12:24:12 GMT

aaron swartz: the early works

I can't stop thinking about, wondering about, caring about, reading about the tragic life of Aaron Swartz. There's a lot I want to write. I think I could fill a book just trying to process what it means, what is an appropriate response, what's it all about. But I'm not going to attempt that.

I've been reading Aaron's blog, on and off, for over ten years. Ten years is a long time. And by my own estimates, those particular 10 years were the longest in history.

Long ago I printed out his HOWTO: Be more productive for multiple re-reads and have returned to it many times since.

I wanted to go back, right back, and try to work out the earliest stuff of his that I read. And I wanted to watch the progression of his ideas as they emerged.

From his blog 'raw thought' -- there's a link to 'Older Posts' which takes you to 'the archive' (grouped by theme).

From there is a link to 'Full Archives' which takes you to the reverse-chronological archives.

These stretch back to May 2005 (the oldest entry on that page is about a server crash after which he had to restart his blogging. Under the so called 'Full archives' section there's no link to anything prior to May 2005.

Now I'm certain he was blogging long before that -- I'm certain I was reading his blog long before that.

Is the stuff before that server crash lost? I hoped not, so I set about locating it.

I clearly remember his powerpoint remix (from 2003!) - it got published in a book of Joel Spolsky's - and I soon tracked that down.

Taking a look at the url suggests a numbered blogging system (from Dave Winer's Radio Userland), and from there it's easy to find all of his prior blog entries.

After a bit of binary searching I found what looks like Aaron's first Hello, world, with article id of '81'.

So I wrote a powershell script to download everything (I hardly think aaronsw would object !!) and found that the articles go from number 81 up to 1691, with a few gaps.

Here's the script.

# Downloads aaron's early stuff
# i've done this the hard way because i didn't have time to do it the easy way.

$client = new-object System.Net.WebClient

$nums = 81..1691

#detected up to 1691  (April 26, 2005)
$nums | % {
    $url = [string]::Format( "{0:000000}",$_)
    $path = join-path $(get-location) ([string]::Format("aaronsw_{0:000000}.html",$_))
    Write-Host "downloading " $url " to " $path
    $client.DownloadFile( $url, $path )
    #sleep for 4 seconds before grabbing, to give the server time to exhale.
    Start-Sleep -s 4

Then I wrote a script to walk through those files and create an archive page in the same style as Aaron's other archive pages.

It's not pretty code, it got the job done...

dir .\aaronsw_*.html | % {

    #extract the filenumber out of the name... i should've made this easier.
    $num = $_.Name.Split("_")[1].Split(".")[0] 
    #calculate the target url for this file
    $url = [string]::Format("{0}",$num)
    #load the file 
    $article = gc $_.Name

    #grab the title
    $titleRegex = [regex]'h1>(.*)</h1>'
    $title = $titleRegex.Match($article).Groups[1].Value
    #grab the time
    $timeRegex = [regex]'<p class="posted">posted ([^(]+) \('
    $time = $timeRegex.Match($article).Groups[1].Value
    #output the url, title and time, as html
    $item = [string]::Format('<p><a href="{0}">{1}</a> ({2})</p>',$url,$title,$time)
    $item >> archivePreCrash.html

So the result is this fairly complete list of pre-server crash articles:


aaronsw archive: early works


Now this takes us up to April 2005. And the post-crash articles start in May 2005, so it probably means that everything's accounted for, except maybe a month's worth of blogging. There are some missing articles within that period, and some lost stuff. I can see that he restored it from the wayback machine where possible, but sometimes there was nothing to grab.

There are a lot of gems in there (and of course a bit of drivel: this starts when he was 15). I was going to pull out a few quotes, but I'd rather let you do that for yourself. He was a thoughtful guy. It'd be great if he was still around.

Read On...

Thu, 10 Jan 2013 21:27:11 GMT

Finding (and removing) duplicate files on your hard drive

I generally hold to the philsophy that hard drive space is cheap, and your time is too valuable to waste on optimising hard drive space.

But one of those fun holiday activities, reserved for times when procrastination is at its peak, is to thoroughly clean up a hard drive and make extra room available.

My usual technique is to use SpaceSniffer (found courtesy of Scott Hanselman's tool list) but this time around I suspected that the biggest waste of space was caused by duplicate files (particularly music and photos) taking up a lot of space.

When confronted with a simple problem, the smart guys look for pre-existing solutions. But not me.

I like to employ something I call the 'my way is the best way' philosophy. Other people call it 'not invented here' syndrome, but I prefer to call it 'my way is the best way' because... well, my way is the best way.

thinking about duplicate files

Analysis is more fun than Action

Most of the duplicate-finding tools in this category have a feature where they will automatically delete all but one copy of each duplicate file found. That's not something I'm willing to do, at least not automatically. What I wanted to do was to create the full list of files, and then analyse it, for example in NimbleText. I wanted to create the list of files and then stand back, thoughfully stroking my long beard, just like Pai Mei from Kill Bill.

So I embarked on a special project, codenamed Dinomopabot, a name recommended by my 5 year old daughter who is very clever at these things. The final result is now named 'Dupes.exe': a command line tool for finding duplicate files on your hard drive.

You can browse, clone or fork the source-code, at Bitbucket:

'Dupes' sourcecode

Or download the executable, ready for use:

Download 'dupes.exe'

Here's the built-in help text:

Dupes Find duplicate files, by calculating checksums.

Usage: Dupes.exe [options]
Tip: redirect output to a .csv file, and manipulate with NimbleText.

  -p, --path=VALUE           the folder to scan
  -s, --subdirs              include subdirectories
  -f, --filter=VALUE         search filter (defaults to *.*)
  -a, --all                  show ALL checksums of files, even non-copies
  -?, -h, --help             show this message and exit

For each file it encounters, Dupes generates a sha256 checksum, with which to compare files. They're short and catchy, they look like this:


Cute hey? Almost adoption-worthy.

And for every member of a duplicate file set that the tool encounters, it spits out a row with four columns, separated by bar symbols ('|')

The four columns are:

CheckSum       Sha256 checksum of the file. (Hint: sort by this to get all duplicates together)
DuplicateNum   0 for the first file in the duplicate set, 1 for the second file, etc.
Filesize       In bytes. (Hint: sort by this, if you want to tackle big files first)
Path           Full path and filename for this duplicate.

So you run dupes.exe and direct the output into a textfile (using > [filename]), and from there you can manipulate it (with NimbleText for example), to create a batch file that carefully deletes all the hand-picked, unwanted duplicates of your choice.

Here's an example of a NimbleText pattern you could use with the output of Dupes. This will create a batch file that deletes all but the first copy of each file:

<% if ($1 > 0) { 'del ' + $3 } %>

That pattern is just a piece of embedded javascript (you can embed javascript in NimbleText patterns) that says "if column 1 is greater than Zero, then output the text 'del ' plus the text from column 3." Column 1 is the duplicate number, so it will be greater than zero for all but the first instance of the file. And column 3 is the full path and filename of the duplicate.

Thank you. I hope someone finds this thing useful. Also, please imagine suitably gigantic and terrifying disclaimers attached to this code. I wrote it after all.

Read On...

Mon, 19 Nov 2012 11:05:41 GMT

Harvey, a .net chat server built with RabbitMQ

I've turned into a rabbid RabbitMQ fan in the last week or two, though so far I've only scratched the surface of what this thing does.

Below I'm going to walk through the code for a chat service, built with .net, that uses RabbitMQ for sending and receiving messages. But first a short discussion of Message Queues, RabbitMQ, and how to get this rabbit up and running.

A lengthy discussion is out of scope for this bus ride, but basically:

A message-queue is a piece of middleware for asynchronous communication. (System A sends messages to System B).

MQ's can be optimized for performance, reliability, scalability or any other '*ility' you can think to mention.

There's lots of them, they make different trade offs. Originally they were expensive proprietary technologies (e.g IBM's MQ-Series) - but along with the rise of standards in this area there have arisen various compelling open source offerings.

RabbitMQ is built on Erlang. I don't want to digress into sounding like one of those Erlang-douchebags, but Erlang is a good match for an MQ.

Erlang's initial purpose was to create telecommunications software that was (a) super reliable and (b) hot-swappable. That's a perfect fit for MQ software. It can spin up extra processes without all the heavy lifting of using extra threads, so where a normal OS thread allocates a few megs of memory, Erlang gets away with a few bytes. Extraordinary stuff.

Having said that, the biggest problem with RabbitMQ is that it's built on Erlang. Thus, to install it on your Enterprise-controlled Servers at BigCo you'll need to get Corporate IT's permission to install yet another VM/Platform. Good luck sweet talking those guys. They do *love* to kick up a fuss.

Up and running with RabbitMQ in Under 3 minutes

Everything I'm going to cover in this section is covered in part 1 of Derek Greer's RabbitMQ for windows series. So I'll go extra quick.

To setup a host server for your chatting you'll need to...

  1. Install erlang:
  2. Set the ERLANG_HOME environment variable to point to the erlang folder under program files. e.g. C:\Program Files\erl5.9.2
  3. Install rabbitMQ:
  4. Enable the rabbitmq management plugin. from an elevated cmd prompt:
        Go to rabbit's sbin folder, e.g. %programfiles%\RabbitMQ Server\rabbitmq_server-2.8.7\sbin, and run:
        rabbitmq-plugins.bat enable rabbitmq_management
  5. To activate the management plugin, stop, install and start the rabbitmq service:
        rabbitmq-service.bat stop
        rabbitmq-service.bat install
        rabbitmq-service.bat start

  6. Finally, visit http://localhost:55672/mgmt/ and see that your rabbitMQ instance is alive.

It's *that* simple.

Worlds easier than most other installs. Much easier than installing a database, or keeping Adobe Reader up to date.

The only other thing you need do to become a certified .net RabbitMQ developer is use nuget to add a reference to the RabbitMQ.client package.

Introducing Harvey (the simple .net chat client)

Harvey Source Code Here.

Once your rabbitMQ service is up and running, every one on your network can grab Harvey.exe and join in one colossal chat room for all their communication purposes. Every message is delivered to every listener.

The architecture is simple. When you run Harvey.exe it creates two channels, one for sending, one for receiving. The send channel is connected to a fan-out exchange on the server. Each snatchy client also creates its own queue on the server (identified by a guid), which is bound to the afore mentioned fan-out exchange. Thus, when any client sends a message, every client receives it.

Let's step through it.

Set up a channel to the fanout exchange

(Just let it wash over you, this will all make sense by the end)

In form_load we setup everything we need for sending messages. We need a channel to the exchange. The exchange is of type 'fanout' meaning it will send all messages to all queues that are bound to it.

When we 'declare' the exchange, the exchange will be created on the server if it doesn't already exist. Otherwise we will use the existing exchange that has already been declared for us.

In form_load:

            var connectionFactory = new ConnectionFactory
                HostName = "localhost",
                Port = 5672,
                UserName = "guest",
                Password = "guest",
                VirtualHost = "/"

            connection = connectionFactory.CreateConnection();
            channelSend = connection.CreateModel();
            channelSend.ExchangeDeclare(exchangeName, ExchangeType.Fanout, false, true, null);

Sending a message

Assuming we have a textbox (txtMessage) for entering the message we want to post, here's what happens when we click send:

            string input =  txtUserName.Text + " > " + txtMessage.Text;
            byte[] message = Encoding.UTF8.GetBytes(input);
            channelSend.BasicPublish(exchangeName, "", null, message);
            txtMessage.Text = string.Empty; 

That was nice, but we probably want to receives messages back as well -- a chat is not just one way.

Set up a channel to your own queue, for receiving.

We declare a queue, a brand new queue that no one has declared before, and bind it to the fanout exchange.

So messages sent to that exchange will go to this queue, on the server. And we've got a channel to the queue.

(This bit also happens in form_load)

            channelReceive = connection.CreateModel();
            channelReceive.QueueDeclare(clientId, false, false, true, null);
            channelReceive.QueueBind(clientId, exchangeName, "");

Receiving a message...

The very next thing we do in form_load, is start a thread for listening to messages on that channel:

            receivingThread = new Thread(() => channelReceive.StartConsume(clientId, MessageHandler));

(Note, forgetting to call .Start() cost me more debugging time than anything else in this whole learning experience)

The following 'StartConsume' extension method was lifted from one of Derek Greer's RabbitMQ articles:

We block the thread waiting for a Dequeue to happen.

        public static void StartConsume(this IModel channel, 
                             string queueName, Action<IModel, DefaultBasicConsumer, BasicDeliverEventArgs> callback)
            QueueingBasicConsumer consumer = new QueueingBasicConsumer(channel);
            channel.BasicConsume(queueName, true, consumer);

            while (true)
                    var eventArgs = (BasicDeliverEventArgs)consumer.Queue.Dequeue();
                    callback(channel, consumer, eventArgs);
                catch (EndOfStreamException)
                    // The consumer was cancelled, the model closed, or the connection went away.

And the 'MessageHandler' delegate, above is as follows:

        public void MessageHandler(IModel channel, DefaultBasicConsumer consumer, BasicDeliverEventArgs eventArgs)
            string message = Encoding.UTF8.GetString(eventArgs.Body) + "\r\n";

            txtConversation.InvokeIfRequired(() =>
                txtConversation.Text += message;

InvokeIfRequired is just a useful winforms extension method for hopping from a background thread onto the gui thread, taken from this stackoverflow question, and implemented as follows:

        public static void InvokeIfRequired(this Control control, MethodInvoker action)
            if (control.InvokeRequired)

Further reading:

This guy used a similar architecture to what i went with. It's just the simplest architecture imaginable, and he handled 2000 messages a second from a very minimal piece of hardware.

Simon Dixon's article - Getting Started With RabbitMQ in .net

Mike Hadlow has written 'an easy to use .net api for RabbitMQ' called EasyNetQ. One to watch.

As recommended above, Derek Greer has an Excellent Series on RabbitMQ for Windows

Further links to .net development with RabbitMQ

Read On...

Mon, 12 Nov 2012 10:08:14 GMT

I'm not just a person, I'm a dot com.

When my website was stolen, and I thought I'd never get it back, I started making plans to re-launch somewhere else. Hence, I acquired the domain

That domain has sat dormant for over a year, until the last week or two, when I decided to put up a list of my online projects, in an easy to digest, html5-friendly, form.

Since you're not doing anything else at the moment, go and have a look:


It's animated using 'isotope' -- an exquisite jQuery plugin for magical layouts.

Read On...

Thu, 01 Nov 2012 12:33:40 GMT

So your domain has been stolen. What now? Taken! Then taken back.

I was recently contacted by a local entrepeneur, Michael Q, after his internet domain was taken in circumstances similar to my own.

An intruder gained entry to his email account and used that to get enough information to transfer ownership of his domain away from his registrar.

His registrar was "crazy domains" (in my case it was 'Go Daddy') and the gaining registrar was a french registrar, (in my case it was, a russian registrar).

Michael and I wrote back and forth a lot over the next few days. I gave him as much advice as I could, and he kept me informed about his progress. On about the fifth day I got the excellent news that he was back in charge of his domain again.

Michael wrote a complete chronology of the incident: How I Lost My Domain Name and How I Got it Back

And here's my own step by step guide to what happens and what to do if your domain is hijacked, based on my experience and Michael's:

Losing and Regaining Your Domain, Step by Step

  1. Notice a warning in your gmail account that you've logged in using an unknown means from a distant location. Your spidey senses will begin tingling.
  2. Check for deleted emails -- find one from your domain registrar, saying you've transferred away from them. This will include details of the gaining registrar.
  3. Panic and or freak out completely at this point.
  4. Check for email rules that automatically delete any emails from the losing or gaining registrar. take screenshots of and then remove those rules.
  5. Secure your gmail account. change your password, change all your security questions and answers, change your recovery email address, disable any third party apps from accessing it, and disable pop and imap access. Start using 2-step verification.
  6. Think about all of the other things you store in your email account. Other passwords in particular. Start the long process of resetting every password you have. Put it in priority order. Use a proper password management system (e.g. password safe) so that all passwords are unique, complex and as long as possible.
  7. Now, and only now, is it time to stop panicking.
  8. All registrars are ICANN accredited businesses. They must abide by a code of practice, or they will lose their accreditation. One of the rules is that a domain can't hop to a new registrar for another 60 days. So breathe a sigh of relief and realise that you have 60 days to regain control of your domain.
  9. Contact your registrar and inform them that your domain has been hijacked and moved to the gaining registrar. Tell them it is a "disputed transfer", and that you want to fill out their disputed transfer away form. See if they have one (they should).
  10. Contact the gaining registrar -- it's their co-operation that will matter the most. Be nice to them. You may need to register at their site, go ahead and do this.
  11. Tell them your domain was hijacked from the losing registrar and moved to them.

    To establish your identity you may need to send them a scanned copy of your identification (drivers license, passport). It's a scary thing to do, but seems to help, so go ahead and do this if they ask for it.

    (It may also, for reasons that are beyond the scope of this article, help to send them a photo of yourself with a loaf of bread on your head)

    Tell them when you first got the domain, what it was used for. Direct them to the way back machine screenshots of your use. If you don't speak their language you may need to find someone to help translate, or fall back to google translate.
  12. If you receive emails from the thief, take screenshots but do not respond. You have nothing to gain by responding. If however you do respond, I suggest you say some scary cold blooded shit like Liam Neeson's character in Taken. His message was perfectly direct:

    I don't know who you are. I don't know what you want. If you are looking for ransom I can tell you I don't have money. But what I do have are a very particular set of skills. Skills I have acquired over a very long career. Skills that make me a nightmare for people like you. If you let my website go now, that'll be the end of it. I will not look for you, I will not pursue you. But if you don't, I will look for you, I will find you and I will kill you.

    On second thoughts, killing people and even threatening to kill people, are considered a tad illegal in most jurisdictions. So you might want to write that email and then delete it without sending it. A better tactic is to try and draw out the hijacker. Ideally you'll get him to explicitly ask you to give him money to get your website back. People have used emails like this as part of the evidence they provide to the gaining registrar.

  13. Once the gaining registrar has established the facts, you should get your domain back. You may not be able to transfer it to the registrar of your choice until the 60 days have elapsed. You may need to wait while they wait for the hijacker to respond to their questions. Naturally the hijacker isn't going to have a very good story, and may simply fail to reply to their questions. But even this takes time. Patience is necessary. Remember you have 60 days.

That's all I've got. If something like this happens to you, or has happened to you, I wish you the best of luck.

Read On...

Sun, 21 Oct 2012 11:25:23 GMT

kv can remember it for you, wholesale


I've started using a groovy little command-line utility found on the internet, and I have to say I am totally enamored of it.

It was brought to my nebulous attention by my conspirator Rhys, who has it in his 'util' folder of little tools, which I've hg cloned onto my own machine and en-pathed.

The tool in question is 'kv', which is short for 'KeyValue'. You can get it here:

Imagine you have a lot of ugly things to remember. I know you do.

For example you may need to remember (and frequently type out) the name of your 'dev' server, prod server, staging server, test server and so on.

Get kv to remember it for you!

At a prompt, type:

kv dev MaxServer0412_Tangerine

Now we've stored the rather cumbersome and hard to remember value 'MaxServer0412_Tangerine' against the nice little key name, 'dev'.

So when you type:

kv dev

Two things will happen: the value will get written out into the console. Okay, sure, whatever. But far better than that: the value will get put into your clipboard.

Rhys uses this to store his jargon file. He works in an industry with a lot of domain specific jargon. Every time he hears a new abbreviation that the business people expect him to know, he adds it to his kv stash.

Also - the values don't have to be simple things. They can be gigantic stuff, for example: the complete works of shakespeares. You can pipe a value, or an entire file into the kv command, just give it a key to use.

type 'completeWorks_of_shakespeare.txt' | kv shakes

If you want it to forget one its keys, use the -r switch:

kv -r shakes 


The tool itself is based on 'boo' by stevenleeg which is itself based on boom by Zach Holman.

It's clearly better than both of those as it has an even shorter name. None of this three or four letter nonsense. Two letters. That's enough.

Here's the help it provides at the commandline:

>kv -?

kv -- a command-line key-value store integrated with the clipboard.
inspired by:


kv name fred smith
saves the value, 'fred smith' under the key, 'name'

kv name
retrieve the value 'fred smith' straight to your clipboard.

lists all keys

kv -r name
will remove the key 'name' (and its value) from your store

And two more tips, for super users:

1. You can also pipe a value in, e.g.

echo Hello Fred | kv Greeting
will store 'Hello Fred' under the key 'Greeting'
type File.xml | kv myFile
will store the content of 'File.xml' under the key 'myFile'

Even though, as I say, I found this after it was recommended by a friend, I have to admit that it's my own tool. I wrote it last year in an hour or so, as a simple demo of a little interface I was dabbling with at the time, called stashy. I immediately forgot about it until Rhys rediscovered it.

Utils Folders! Utils Folders! Utils Folders! Utils Folders!

Rhys's 'util' folder is a thing of joy. I think he should make it globally available so people everywhere can clone it, fork it and so on.

I even have a name for it: Rhys's Pieces. Clever hey, Rhys?

Got any little tools in your own utils folder?

Or any way you share your utils folder?

[Image above is of a KV Tank (Kliment Voroshilov), no relation.]

Read On...

Wed, 10 Oct 2012 11:23:32 GMT

Hello IT Department

At one time in my long and extraordinary career (*cough* today *cough*), I had a problem where an offshore IT department stopped replying to my emails. They had closed a support request as complete when it wasn't, and they ignored my every plea to have it reopened. Here's the email I sent, which successfully reopened the thread of communication.

From: Leon
To: IT Support
Subject: IT Service Desk request number SR0154899389 completed


Please reopen this ticket.

It has been marked as complete but it is not complete.

I have written asking for this to be reopened four times now with no response.

Here is a picture of David Boon.

The pool we are running in the office suggests that I will need to send this email eight times before I do get a response.

Since my money is on just sending it four times, you could help a brother out and respond to me this time. Then I win!

(actual picture may not be David Boon)

You are welcome to reuse it if your plight resembles mine.

Don't worry if you don't know who David Boon is. It kind of helps if you don't. Random inclusion of an unrelated photo seems to be the key factor in inspiring a call to action. I must A/B test this idea against several indifferent IT departments.

(Image of Rob Sitch as an Oz Brother, courtesy of champagne comedy forum).

Read On...

Fri, 21 Sep 2012 11:20:37 GMT

Dialog Between a Man and His Vista Laptop

original article before discard

While continuing the cleanup instigated by the previously mentioned documentary, I threw out quite a lot of stuff.

One piece of paper had the following dialog that I transcribed before discarding. It concerns a man and his Vista laptop.

—Hello laptop.
—Hello user!
—I'd like to change some settings, can I open the control panel?
—[long, long pause] No problem!
—I want to change what happens when I close the lid. What happens currently?
—[extended pause] Well that depends if I'm on a battery or plugged in.
—Why, what's the difference?
—[assume long pauses unless told otherwise] Well, if I'm on battery and you close the lid, I go into sleep mode.
—And? If you're plugged in?
—Well, if I'm plugged in and you close the lid, I go into sleep mode.
—That's the same isn't it?
—Well, I kill a few apps, just to spice it up.
—I see. So what is sleep mode?
—It's a low power mode where applications are paused.
—No, that's suspend.
—What's suspend?
—It's a bit like hibernate.
—Oh. What exactly is hibernate?
—Well... it's somewhat similar to sleep.
—What's the specific difference between all of those?
—Hmmm. Well, let me see. It's very... There's... Well Okay. I'm not completely sure myself. So I just delete a few extra files to make it convincing. Ah, anyway, you were wanting to change a setting?
—Frankly, I'm a little concerned now. But all I want to do is make sure that if I just close the lid, and if you're plugged in to a power supply, then I want you to just do nothing.
—Just pretend like nothing's happened. Pretend I haven't event touched the lid.
—Can I kill some apps?
—Delete a few smallish files?
—Move the swap file around on disk. Jiggle it a bit?
—Not even that.
—What if I 'clean up' the registry or terminate some services?
—No, not that either.
—Nothing fancy at all?
—Okay, Sir. It's your dime.
—So when I shut the lid, while you're plugged in to a power supply, what are you going to do?
—Nothing much.
—Nothing much?
—Okay, nothing at all. I'm going to pretend you haven't even touched the lid and that you're still watching very closely. I can do this. I'm a pretty sophisticated operating system you know. I'm not some version two or three operating system. I am Windows Vista, the most eagerly anticipated operating system in the history of windows operating systems. All of this tricky 'do nothing stuff' is considered elementary to a system like me. Go ahead.
—Okay here we go.
—No problem! Bring it on.
—You're definitely ready?
—Ready as ever. A little bit excited actually.
—Here goes.
Man gingerly closes the lid. Without a pause we hear the hard drive grind to a halt. Lights flicker out.
[man performs a facedesk]

Read On...

Fri, 07 Sep 2012 13:50:48 GMT

NimbleText 1.6, Codename Jetboat

Jetboat, the mildly anticipated new release of NimbleText is out now.

If you don't already use NimbleText every single day then you're missing out. NimbleText is a tool for manipulating little bits of data, for formatting text, for performing ad-hoc code generation. It's a versatile little tool that every programmer, DBA, sysadmin, knowledge worker and techie should keep within reach. Here's a two minute guide.

Download NimbleText

Here's a quick rundown of the new features:

Header Variables

You can now refer to the first row of the data from inside any row, using a '$h' pattern.

The new feature works like this. Say you have some simple data that includes a header row:

name, age
Jim, 126
Jenny, 4

Within your pattern you can refer to the first item in the header as $h0, and the second item as $h1, and so on. Like this:

The person with $h0 $0 has $h1 $1

The result will be:

The person with name Jim has age 126
The person with name Jenny has age 4

This basically means you can stash 'global variables' into the first row and access them in your pattern. Which means you can reuse your patterns more often.

Counting from the right.

Sometimes the data you are parsing is 'jagged' meaning different rows have a different number of columns. This can happen for a variety of reasons. In NimbleText we can't pick and choose the data we are handed. We just do our best to handle for what we get.

When you have jagged data, you often want to read the last column, or the second last column: basically you want to count the columns starting from the left. For example, here's some sporting data:

Name, Scores (ascending)
Stu, 0, 0, 1
Jim, 1, 2, 2, 3, 8  
Stacey, 0, 0, 1, 3, 3, 9, 9

Notice there is a different number of scores for each player. If you only want the last score you can use a negative index to count from the right:

The best score for $0 is $-0


The best score for Stu is 1
The best score for Jim is 8
The best score for Stacey is 9

Download it now, or use the online version.

Release notes are here.

Read On...

Fri, 31 Aug 2012 06:02:53 GMT

On Task Hoarding and Todo Bankruptcy

Last week I watched a British Channel 4 documentary about a chronic hoarder named Richard Wallace. Fascinating stuff.

This was a man who hadn't had a bath in years because his bath, like everything else in his house, was covered to the ceiling in piles of collected junk. To get from one room to the next he would have to swim over the top of his junk pile, ducking under the top of the doorway. And yet he was a fairly normal guy. He wasn't like some angry Smaug, fighting to protect his golden hoard. He had a well developed sense of humour, and you could carry out a normal conversation with the guy.

Yet he had a profound lack of insight. Despite his incredible existence (he slept in a chair, his bed was covered in ceiling-high junk), he didn't see see that he had a psychological syndrome. Pay attention to this, because it's kind of the point: He didn't believe he had an excessive hoarding habit, he felt his real problem was a shortage of storage.

I think what scared me was that he was a little like me. Or a little like you. So it got me thinking about my own hoarding tendencies.

It's normal to do some amount of collecting. I've always done a little here and there. I have boxes and boxes of books under the house. I have a record collection somewhere. I have a jar of buttons (more on that later). But all of that is under control. (After watching the documentary I immediately threw away a box of msdn magazines that I've been holding onto for too long.)

Instead, there is a completely different form of hoarding I engage in, that has gotten out of control.

The thing I collect is incomplete projects. Unfinished work.

My list of incomplete projects is my own personal crazy hoard.

To get from one task to the next, I need to swim over the ceiling-high pile of incomplete tasks, stacked up from every stray project idea I've ever had.

Like a crazy hoarder I mistake the root cause of my growing mountain of incomplete work. The hoarder thinks he has a storage problem (when he really has a 'throwing things away problem'). I say I am 'time poor' as if the problem is that poor me is given only 24 hours in a day. It's more accurate to say... what exactly? It seems crazy for a crazy person to use his own crazy reasoning to diagnose his own crazy condition. Maybe I too easily add new projects to my list, or I am too reluctant to exit from unsuccessful projects. Perhaps I am too reluctant to let a task go, to ship what I've done. They're never perfect, never good enough.

And I know I'm not alone in making the easy claim that I am 'time poor'. So many people claim to be time poor, when really we are poor at prioritizing, or poor at decisiveness, or don't know how to say 'no' ( other people, to our own ideas).

If only I had a hidden store of time, or if only I had magical organisation tools, or if only I could improve my productive throughput, then, only then would I be able to get things done, to consolidate the growing backlogs and todo lists into one clear line of work, and plough through it like an arctic ice breaker carving its way through a sheet of ice.

So I have to declare todo bankruptcy. Throw everything out and start again.

I've gone back to the trello boards and slashed and pruned and archived and revised and reordered until the whole todo landscape started to make sense. I've dragged in items from other sources (from moleskine's and from starred items in gmail, from 'TODO' comments in my code, from various TODO.txt files buried on my hard-drive... from all over.)

First up, a lot of projects have moved from the maybe pile to the 'never no way' pile.

Example of projects that are officially cancelled as of this moment are:

Not To Do

  1. 'Cop Dog Buddies' -- movie script about two mismatched police dogs thrown together to hunt down their masters' killers.
  2. 'Registry on Rails' -- the web development framework from hell.
  3. Orable -- (pronounced "'orrible") my poor man's oracle IDE
  4. OCD-targeted one-page website "have i left the iron on?"
  5. A life-sized full-body tattoo of my own body, all over my body.
  6. My pro wrestling career
  7. My rap battle ambitions
  8. A range of Pinal Dave T-Shirts
  9. Twee -- a micro-blogging service where posts can only be three words long and must be valid dictionary words in your language.
  10. 'Vampurr' trilogy -- epic love-triangle between goth-girl tattooist, ear-stretching vampire and shape-shifting battle-cat.
  11. Word as a database -- it's Word. As a database.
  12. Operation Butter-knife
  13. Choosing the right fonts
  14. Operation 'Taser my enemies in the face'
  15. Boss monsters feature in unreleased malware easter egg
  16. 'Silmarillion with sock puppets' -- treatment for a feature film
  17. 'Top Gut' -- movie script about the fat camp for the fattest of the fat

Okay, that's a slightly modified version of the real list. The real list is a lot longer and a lot sadder. But the actual thing I'll actually do next is:

To Do

1. Put out NimbleText 1.6.

People have been nagging me about this for a while, and it's pretty much ready, if I can just stop distracting myself with all the other craziness.

Stay tuned.

Read On...

Mon, 16 Jul 2012 11:53:25 GMT

Developer UI Done Right: Mercurial Commandline!

Developer tools are famous for having bad usability. In Code Complete Steve McConnell listed this as a case of 'the cobbler's children go barefoot'. (A fancier term for the same effect is 'vocational irony.' you know, like House MD).

But here's a case where User Experience in a very very developer-specific tool is surprisingly polished, in a way that you wouldn't quite expect.

Follow along if you will...

I'm using mercurial and I decide my work is ready to be pushed. At this point, the stack of tasks in my head (the things I'm trying to achieve) just says "push."

I try to push.

C:...>hg push
pushing to ...
searching for changes
abort: push creates new remote head a751ec334b3e!
(you should pull and merge or use push -f to force)

Interesting! It failed, but not in the typical 'pages and pages of angry red error messages' way. Instead I get a one line error description and then this delicious hint -- I can use 'pull and merge' to get past the problem.

(Note that I've elided any personal details, and hashes have been modified to protect the innocent)

So now the stack in my head says "pull, merge, push".

So I pull.

C:...>hg pull
pulling from ...
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 1 changes to 1 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)

This succeeded nicely. But again there is a hint. Having performed the pull, it looks like I need to merge.

The hint reinforces what the previous command told me and helps me to confidently move in the direction I was already headed. (Or: it serves to remind me that I need to merge, in case I had forgotten). The stack in my head now says "merge, push."

I attempt the merge.

C:...>hg merge
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, don't forget to commit)

It tells me the merge succeeded. This is pretty spectacular all by itself, but for users of distributed version control systems it's a common enough occurrence, so I'll skip over that bit. Again, I get a neat little hint. It reminds me to commit before I do anything else. So the stack in my head now says "commit, push"

I attempt to commit...

C:...>hg commit

This last command gives me only happy messages, which I've not included as they're of no interest. There is no hint what to do this time, as mercurial does not remember that my ultimate goal here was to push. But I haven't forgotten that simple goal. So I try the last remaining step: I push.

C:...>hg push
pushing to ...
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 1 changes to 1 files

And everything is right in the world.

There's something just so neat about the hand-holding that mercurial performs throughout the exercise. I want to pick it up and cuddle it and rub my nose against its little nose.

(of course frequent mercurial users will know shorter and slightly better ways to achieve this same thing, but these little step by step hints are completely adequate for the occasional user like me.)

Now why was all of this amazing? As I said, it's a developer tool, so that's already a good reason to expect poor UI.

But secondly, it's an open source tool. There is a belief that open source software favours usability less than other things.

Third, the hints that were so helpful are a form of documentation. And open source projects very often get criticised for their lack of documentation. Again we have a nice counter example.

Fourth -- it's a commandline tool! A commandline tool! This is a category of software that is not known for being helpful and forgiving to the beginner or infrequent user. Yet mercurial is demonstrating a way in which it is possible to be kind to such users.

All up: I continue to find it nice on a whole bunch of levels. Hat tip to mercurial.

(Next article in this series: "Mercurial And How To Undo a 'hg -forget *' Command, Or, Mercurial, You Evil Unusable Bastard, Why Hast Thou Forsaken Me? Undo! Undo!")

Read On...

Fri, 25 May 2012 13:36:19 GMT

Rediscovering the Amstrad CPC 6128

I recently inherited the original instruction manual from the first computer my family ever owned, the Amstrad CPC 6128 User Instructions.

Flicking through this magnificent compendium has sent me on a serious nostalgia trip. It wasn't long before I downloaded an Amstrad emulator (or two) and began to relive some of the programming fun of Amstrad Basic.

The book takes you through every aspect of the computer, the hardware, the operating system, and two programming languages (BASIC and Logo). And it starts from absolute beginner level, in a way that no modern set of instructions ever needs to. Here's an excellent example:

When you reach the right hand edge of the screen by entering 40 characters on a line, the next character will automatically appear on the following line at the left edge of the screen. This means that you should NOT press [RETURN] as those of you accustomed to typewriters might press a carriage return towards the right edge of a page.

The computer does this automatically for you, and will react to an unwanted [RETURN] by printing an error message - usually a Syntax error, either there and then, or when the program is run.

...that's not a detail typically cover in a more recent text. And it recurs throughout the early chapters of the book, as they explicitly tell you where to hit return in case you've miraculously forgotten. They only stop adding the word [RETURN] when they get up to teaching you about the return keyword (used after a gosub, for awesome fun times.)

Demonstrating the use of GOTO, GOSUB and RETURN leads to this interesting reflection:

See how much tedious typing we've saved ourselves? Well designed subroutines are a principal part of computing. They lead to 'structured' programs, and develop good programming habits.

...all by itself this seems to conflict with the ideas put forth in 'Go-to Statement Considered Harmful' but the very next paragraph really takes it up a notch:

Always bear in mind when writing sub-routines, that you do not necessarily have to Jump into' the sub-routine at the same point, i.e. its beginning. A sub-routine written from lines 500 to 800 can be called by: GOSUB 500, or GOSUB 640, or GOSUB 790.

...this isn't what you call the gold standard of structured programming. ;-)

The more I got into it, the more I enjoyed it. I was surprised at how much I'd forgotten, but equally surprised at how ready those memories were to spring back into place. My friend Dr Richard (of brisbane parks fame) pointed out that by reawakening such old neurons and marking them as new again, the brain is bound to believe that those memories are of very high importance and mark them as always hot. So now it's likely I'll never forget Amstrad Basic again.

One intriguing idea from the Amstrad, which seems to have been abandoned by the side of the information highway, is 'the copy cursor'.

Consider this startling example of using 'the copy cursor' to correct a typo. Their example builds on this code sample, which has a missing 'r' on line 10:

10 input "what is you name";a$ [RETURN] 
20 input "what is your age";b [RETURN]
30 print "I must say";a$;" you dont 
look";b;"years old" [RETURN] 

Here's how a coding ninja would fix that typo, in the copy cursor era:

Copy Cursor Method
The copy cursor is another cursor (in addition to the one already on the screen) which comes into view when you hold down [SHIFT] and press one of the cursor keys. It then detaches itself from the main cursor and can then be moved around the screen independently.

To correct the mistakes in line 10 and 30, hold down the [SHIFT] key then press the cursor up key until the copy cursor is positioned over the very beginning of line 10. You will notice the main cursor has not moved, so there are now two cursors on the screen. Now press the [COPY] key until the copy cursor is positioned over the space between 'you' and 'name'. You will notice that line 10 is being re-written on the last line and the main cursor stops at the same place as the copy cursor. Now type in the letter 'r'. This will appear on the bottom line only.

The main cursor has moved but the copy cursor stayed where it was. Now press the [COPY] key until the whole of line 10 is copied. Press [RETURN] and this new line 10 will be stored in the memory. The copy cursor disappears and the main cursor positions itself under the new line 1 0. To correct the second mistake, hold down [SHIFT] and press the cursor up key until the copy cursor appears over the very beginning of line 30.

Press [COPY] until the copy cursor is positioned over the quotation marks next to say. Now press the space bar once. A space wiil be inserted on the bottom line. Hold down the [COPY] key until the whole of line 30 is copied, then press [RETURN].

(Using an Amstrad emulator with a windows keyboard, I found that the Pg-Dn key acted as the [COPY] key).

But software quality assurance and refactoring magic aren't just left up to the wonderous copy cursor. There's another awesome tip on detecting errors in your code. The trick is to write your code in lowercase and see that the interpreter finds your keywords and shifts them to uppercase:

In the above program, and in later chapters and listings in this manual, BASIC keywords will appear in upper case (CAPITAL) letters. This is how keywords appear when a program is LISTed by the computer. In general it is preferable that you type instructions or programs using lower case (small) letters, since it will help you spot typing mistakes when LISTing the program - (because the mis-typed BASIC keyword will NOT be converted to upper case).

I find something adorable in their vociferous way of describing the technique. The modern age is all too brief in its belting-around-the-headedness-about-the-simple-things. These days it's all "merge this, rebase that, man page if you don't grok" and the eyes are left spinny.

I've had some recent fun building simple programs on the Amstrad (emulators) but there's too much to cover here. I'd like to write a little about it, if I find the time, but that's enough for now.

Just reviewing the book was a joy in itself. Whoever said "nostalgia isn't what it used to be" must've been one of those filthy Commodore 64 programmers, I guess.

Read On...

Sat, 12 May 2012 02:59:08 GMT

Just Wally

The apocalypse came suddenly. Some kind of worm, virus, trojan -- some kind of Mark Russinovich doomsday scenario. It spread so fast no one had a chance to react. It lit up every computer screen, obliterating every computer user in the world. Every last worker was obliterated, right at their desk. All that remained was a tiny pile of ashes on every seat.

Only Wally was spared. While everyone else was at the desks working, Wally was wandering the halls, holding a coffee cup.

'Just Wally' is a cartoon that removes all the unneccessary elements from Dilbert, and leaves just the hero himself, Wally, wandering the empty building, holding meetings with himself, filling his loneliness with imagined interactions.

Wally has always been the truest character in Dilbert. I've met a few Dilberts in my time. I've met a few Pointed Haired Bosses. But just about everyone is at least part-Wally. And more than a few have been pure-Wally. You know who you are.

Some people theorise that the true story of 'Just Wally' is that Wally is the one who died. This is his limbo, wandering alone, unable to interact with the living.

Others say Wally has fallen into a coma. This is his extended delusion. He cannot tell dream from reality, sarcasm from seriousness. What exactly is a dream? What exactly is a joke?

The words of JD Salinger are relevant here, as always.

"It isn't just Wally. It could be a girl, for goodness' sake. I mean if he were a girl - somebody in my dorm, for example, - he'd have been painting scenery in some stock company all summer. Or bicycled through wales. Or taken an apartment in New York and worked for a magazine or an advertising company. It's everybody, I mean. Everything everybody does is so - I don't know, not wrong, or even mean, or even stupid, necessarily. But just so tiny and meaningless and - sad-making.

And the worst part is, if you go bohemian or something crazy like that, you're conforming just as much as everybody else, only in a different way."

Tiny and meaningless and sad-making.

Tiny and meaningless and sad-making. 'Just Wally' makes us stop and ponder the futility of everything we do, everything we think and everything we are.

In the style of Garfield minus Garfield, Just Wally plays upon the maxim of my old buddy Antoine de Saint-Exupery:

"Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away"

Read On...

Tue, 08 May 2012 04:22:21 GMT

The Correct Order for a First Time Viewing of The Lord Of The Rings

After reading Scott Hanselman's post about introducing your younglings to Star Wars, I was intrigued by the suggested 'Machete order' (courtey of Rod Hilton)

  • 4 - Star Wars: A New Hope
  • 5 - Empire Strikes Back
  • 2 - Attack of The Clones
  • 3 - Revenge of the Sith
  • 6 - Return of the Jedi

Which lead to deep conversations with myself about which order I should use when introducing my daughers to 'The Lord of the Rings'.

The three films can be arranged into 6 possible non-repeating combinations:

  • Fellowship, Towers, King
  • Fellowship, King, Towers
  • Towers, Fellowship, King
  • Towers, King, Fellowship
  • King, Fellowship, Towers
  • King, Towers, Fellowship

All of which have their own pluses and minuses, but none of which would qualify as a true 'machete' reordering.

I finally settled on the following order, which you'll agree is the best possible version of events:

  • 1. The Two Towers -- A good story always starts in the midst of the action, and leaps past the boring parts.
  • 2. The Hobbit, An Unexpected Journey -- having established the story we now move learn the origin of the Ring and Gollum.
  • 3. How to Train your Dragon -- the loveable Toothless and Hiccup show us that not all dragons are nasty Smaugs.
  • 3a. Read all of the books -- that way you can complain bitterly about the missing 'Scourge of the Shire' segment during:
  • 4. Return of the King, Disc 2 -- 5 minutes of chucking a ring in a pit, a quick eagle ride, and two hours saying goodbye.
  • 5. Return of the King, Disc 1 -- Awesome battle scene. Best war ever.

I dub this the Chop-Suey Reordering, and in line with Oracle's copyright on the arrangement of the Java Api's, I claim ownership of this and all derivative reorderings of the LOTR franchise.

Read On...

Fri, 23 Mar 2012 12:37:13 GMT

A new era for Android.

Occasionally, marketers send me press releases in the hope I'll blog about them. Ordinarily I refuse to be manipulated by such a ploy, but I thought this one about android was worth a little discussion. I've always thought that android phones look interesting but only from the point of view of a tinkerer. This new direction seems to offer something more.

Here's a few relevant excerpts:

food phone

Android, the world's leading free, open source platform for everything beyond smart phones, and the world's most popular phone amongst Android software developers and Google employees, is proud to announce the discovery of their first Consumer.

The Android developer community first suspected the existence of the Consumer after finding non-Google IP addresses in the log file of an Android Developer Forum. The discovery was quickly escalated to Google management who sent a rapid response Privacy Intrusion Team to perform expanded analysis of his web searches, browser, email and telephone usage. They were thrilled to discover that the lurker was a genuine Android customer who was neither an Android software developer or a Google employee.

The potential existence of such a Consumer had been hotly debated on Android developer forums for years. But even the most optimistic Android enthusiasts had assumed that the debate was purely theoretical.

Google had previously spent millions of dollars placing 'Angry Birds' in their 'Google Play' app store, in the hope that it could potentially attract a Consumer to consider using the Android platform for Consumer Purposes. Google's Privacy Intrusion Team have revealed that analysis of the Consumer's correspondence offer no clear rationale for why he purchased an Android phone from a market place crowded with more suitable offerings. Skeptics have taken this as an indication that the Consumer's existence could be the result of Google Finland's controversial 'tag and release' program where members of the public were anaesthetised, given an Android phone, and released back into the population.

This new phase of the Android platform is an exciting time. Predicting an influx of Consumers, developers have quickly raced to make the phone more technically intimidating and to provide an even more fractured range of devices. Google employees remain unaware of anything that has happened to non-Google employees.

The Consumer is now considering getting into Android development, and has recently taken a job at Google.

Crazy times. Next they'll be announcing the discovery of a teenager who wants a Zune.

Read On...

Sat, 07 Jan 2012 10:57:31 GMT

Mind-boggling Demo of New Gaming Genre, aka Folder-Based Hangman, aka Fun with Recursion

I had a crazy idea recently for a new game - a game that defines an entire new *genre* of computer game, and a new style of programming computer games. Whether or not this idea will go on to change the way all computer games are written, I will let history decide.

It's such a simple idea that I don't know how it couldn't have possibly existed earlier. It doesn't require massive graphic capabilities, no CUDA NUMA GPGPGPU and the like -- it's an idea so profoundly simple that you'll be scraping your jaw off the floor with a spoon before you finish reading this blog post.

You run the 'game' and it sets up a directory structure to represent every possible state of the game. To play the game, you inspect the current folder, look at the currently available sub folders, and choose which one to navigate into. Each sub folder you see represents the next possible state of the game.

There is no executable program running when you are playing. The game is just your act of navigating the folder structure. It's a clever form of madness!

Here's some screenshots that show me playing the game, in a command prompt.

I've changed my prompt to just a 'greater than' sign, by typing 'prompt $g', to make it cleaner. Old-school DOS wizards do this kind of thing all the time. Hipster kids, try and keep up.

First I type 'dir /b' to get a clean view of the current folder.

There is only one folder, '__PLAY HANGMAN__' so I navigate into it by typing  'cd[TAB][Enter]'. The game has begun.

Looking in that folder I see the empty scaffold, three underscores (representing a 3 letter word) and the available letters listed down the left hand side. We're playing with a reduced alphabet to keep the number of permutations within a reasonable amount.

My first guess is the letter 'A'. To make this guess I type 'cd A[tab]'. When I type 'dir /b' to inspect the new state of the game I see that it was a good guess, as one of the letters of the word has been filled in. Also there is an 'x' next to the 'A' indicating that that letter has been guessed. That's all there is to it. Hear that pop? That was your cerebellum exploding through your temporal lobe.

If I try guessing 'A' again, all I find is a folder containing a file named 'You have already guessed that letter.' To undo my mistake I back out by typing 'cd ..' (You could, theoretically use this technique to undo any move, but that would be unsportsmanlike.)

A couple of moves later and I've guessed every letter:

The word is 'CAB'. There's no particular fanfare. Just the word 'WIN' declaring my victory.

Okay, now you've seen the whole thing I hope you're aching to not just download the game, but to write your own entry into this brave new genre. You could do for Gehtto-Folder-Games what John Carmack did for first person shooters!

I'd love to see an implementation of tic-tac-toe, aka, naughts and crosses. Also, hangman could be minified by using junctions (i.e. symbolic links) -- I'd love to see that implemented. The possibilities for new games are pretty much endless. Maybe six or seven.

Okay let me level with you. The mathematics of this idea were just ridiculous. For a full 26 character alphabet, I would've killed my little computer. (Care to accurately calculate how many folders are created for the given alphabet?) It's all based around N-factorial where N is the size of the alphabet. Factorial is not something you want to see in the real world.

I'm on holiday at the moment, so the only computer available to write it on was my dell mini, which doesn't have any serious coding environment. So rather than write it as a console app in visual studio (or even a powershell app) I wrote a javascript page that generates a batch file. It's very niche.

This also turned into an opportunity to learn the ins and outs of getting recursion wrong with javascript. The most common mistake you make with recursion in javascript, it turns out, is forgetting to declare a local variable. This means that the variable becomes global and your recursion goes nuts. Don't make that mistake. When your code is creating subfolders all over your hard drive it's a particularly painful mistake. It took me considerably less time to write the program than it did to debug it, and (considerably*considerably) less time to debug than the time to clean up all the folders left in unexpected places.

But the funnest bit was the ascii sprite code.

I had one array that showed the final hanged man:

var hangyPicture = [
'   _______   ',
'   I     I   ',
'   I     O   ',
'   I   --I-- ',
'   I    I I  ',
'   I         ',
'--===--      '];

(Side point... why wasn't my ascii art better than this? Because | and \ are not valid in folder names.)

And I had another array that showed how many misses were required before a given character of the hangyPicture was shown:

var hangyMask = [
'             ',
'             ',
'         1   ',
'       33233 ',
'        4 4  ',
'             ',
'             '];

Then, with those two arrays in place, I can work out the names of the folders to create. I walk through the mask, one character at a time, and compare the digit I find to the current number of missed guesses. If the digit I find is less than (or equal to) the current number of missed guesses, then I include that character in the folder name, otherwise I mask it out with a space. Ah, I give in -- it's easier to just show the code:

for (var h in hangyPicture) {
  // use hangyMask[h] and numberOfMisses to mask chars out of hangyPictures[h] 
  for(var i = 0; i < hangyMask[h].length; i++) {
    if (hangyMask[h][i] == ' ' || hangyMask[h][i] <= numberOfMisses) {
      folders[h] += hangyPicture[h][i];
    } else {
      folders[h] += ' ';

Okay. Now you've been enlightened with the future of ultra-ghetto folder-based gaming, go ahead and make your own. I can wait.

Here's the code

The accompanying program is a piece of javascript that creates a windows batch file. You run the batch file.

Read On...

Sun, 27 Nov 2011 03:07:28 GMT

Got CSV in your javascript? Use agnes.

The only things that will survive the forthcoming nuclear+zombie apocalypse are cockroaches, javascript and CSV.

So I've written an open source javascript library, agnes.js, that the cockroaches can use for dealing with CSV from javascript. And in the brief pre-apocalypse era you can use it too.

Download the zip

I've written before about how CSV starts off looking easy, but quickly descends into a world of insanity. So in javascript land, let agnes handle all the nasty quirks and edge cases (embedded delimiters, qualifiers, nulls and so on).

I wrote a bunch of unit tests to go with it, so you can tell exactly what it does with each weird bit of input you can throw at it.

You can download it from

This was a particularly fun little bus project, and what I like best about agnes is the content you get when you download her.

The readme file has executable examples, that work by having a chunk of code displayed in a div, which is the exact code that is grabbed and executed when you click 'Try it'.

Browse source code

I like the unit tests that come with it, and the little unit test runner. I could've gone really overboard with it, but I stopped myself before it went too far.

And I like the sample that performs Csv to Json conversion, back and forth, back and forth. My favourite part of that is using html entities in the button titles, for left and right arrows.

Try it out

Now that I've got agnes out of the way, hopefully I can focus on my new bilion dollar idea,

Read On...

Sat, 12 Nov 2011 00:39:08 GMT

I went to write down a book name and founded an internet empire instead.

tron motorcycle just 55K AT AT dog costume you must have

Yesterday Joel told me, 'hey you really should read "The Big Short" by Michael Lewis' -- and I thought, yes, I'll write that in my list of books I must get and when I have a chance I'll order it and all the other books in my list of books i must get.

Looking through my iphone I was shocked to find I don't even *have* a list of books I must get. I've got a list of which Woody Allen movies I haven't seen, and I have a list of which Jeeves and Wooster books I own (or own twice) so I don't accidentally buy them again (or again again), but no "Books I must get".

And I realised it's not just books that I keep forgetting. It's everything in our stupid materialist world. It's gadgets, music, movies, games, t-shirts, toys, gifts for my wife, baby stuff, apps, power tools -- a whole big fat materialist world full of stuff I must get, that, realistically i'll never get, but which my inner taxonomist wouldn't mind having a list of somewhere.

Suddenly, before I could stop them, my hands had rushed off and spent 9.95 to buy all of the following websites...


...and so on, because i bought ''.

And now I have a slight dilemma. I already own too many urls that I'm not using (this brings my total internet empire to 11.5 sites) And I don't have time to execute on even the simplest ideas in my idea log.

So: how can I crank out a social recommendation/shopping app in under 5 bus trips!?

I want something that produces an output a little bit like this is why i'm broke dot com but where the recommendations come from people i respect, and with affiliate dollars flowing into my wallet on every recommended purchase. (And i'd like to come up with a less-sleazy way to monetize, if possible, but I do have to recoup that $9.95 somehow)

I've begun by creating a Trello board to capture all my ideas. I've got details for the home page, a products page, a user page, and a topic page. I've got a backlog of features that I won't implement at first, and I've got a list of ideas for what technology I'll use where. Next I'll put together some screen mockups and put them in front of my extended team of insult generators lunch buddies.

In the mean time I'll need to keep a cricket bat handy with which to repel the hordes of nodding VCs.


Read On...

Hey good looking!

click here to visit the secretGeek archives!

Go on... continue through to the archives



The Canine Pyramid The Canine Pyramid
Humans: A Tragedy. Humans: A Tragedy.
OfficeQuest... Gamification for the Office Suite OfficeQuest... Gamification for the Office Suite
New product launch: NimbleSET New product launch: NimbleSET
Programming The Robot from Diary of a Wimpy Kid Programming The Robot from Diary of a Wimpy Kid
Happy new year 2014 Happy new year 2014
Downtime as a service Downtime as a service
The Shape of Your Irrationality The Shape of Your Irrationality
This is why I don't go to nice restaurants any more. This is why I don't go to nice restaurants any more.
A flowchart of what programmers do at work all day A flowchart of what programmers do at work all day
The Telepresent Man. The Telepresent Man.
Interview with an Ex-Microsoftie. Interview with an Ex-Microsoftie.
CRUMBS! Commandline navigation tool for Powershell CRUMBS! Commandline navigation tool for Powershell
Little tool for making Amazon affiliate links Little tool for making Amazon affiliate links
Extracting a Trello board as markdown Extracting a Trello board as markdown
hgs: Manage Lots of Mercurial Projects Simultaneously hgs: Manage Lots of Mercurial Projects Simultaneously
You Must Get It! You Must Get It!
AddDays: A Very Simple Date Calculator AddDays: A Very Simple Date Calculator
Google caught in a lie. Google caught in a lie.
NimbleText 2.0: More Than Twice The Price! NimbleText 2.0: More Than Twice The Price!
A Computer Simulation of Creative Work, or 'How To Get Nothing Done' A Computer Simulation of Creative Work, or 'How To Get Nothing Done'
NimbleText 1.9 -- BoomTown! NimbleText 1.9 -- BoomTown!
Line Endings. Line Endings.
**This** is how you pivot **This** is how you pivot
Art of the command-line helper Art of the command-line helper
Go and read a book. Go and read a book.
Slurp up mega-traffic by writing scalable, timeless search-bait Slurp up mega-traffic by writing scalable, timeless search-bait
Do *NOT* try this Hacking Script at home Do *NOT* try this Hacking Script at home
The 'Should I automate it?' Calculator The 'Should I automate it?' Calculator

Archives Complete secretGeek Archives

TimeSnapper -- Automated Screenshot Journal TimeSnapper: automatic screenshot journal

25 steps for building a Micro-ISV 25 steps for building a Micro-ISV
3 minute guides -- babysteps in new technologies: powershell, JSON, watir, F# 3 Minute Guide Series
Universal Troubleshooting checklist Universal Troubleshooting Checklist
Top 10 SecretGeek articles Top 10 SecretGeek articles
ShinyPower (help with Powershell) ShinyPower
Now at CodePlex

Realtime CSS Editor, in a browser RealTime Online CSS Editor
Gradient Maker -- a tool for making background images that blend from one colour to another. Forget photoshop, this is the bomb. Gradient Maker

[powered by Google] 

How to be depressed How to be depressed
You are not inadequate.

Recommended Reading

the little schemer

The Best Software Writing I
The Business Of Software (Eric Sink)

Recommended blogs

Jeff Atwood
Joseph Cooney
Phil Haack
Scott Hanselman
Julia Lerman
Rhys Parry
Joel Pobar
OJ Reeves
Eric Sink

InfoText - amazing search for SharePoint
LogEnvy - event logs made sexy
Computer, Unlocked. A rapid computer customization resource
Aussie Bushwalking
BrisParks :: best parks for kids in brisbane
PhysioTec, Brisbane Specialist Physiotherapy & Pilates
home .: about .: secretGeek RSS .: © Leon Bambrick 2012 .: privacy

home .: about .: RSS .: © Leon Bambrick 2012 .: privacy