S Anand

Launching applications

Opening programs from the Start – All Programs menu is painful. For many years, I relied on the quick launch bar.

QuickLaunch

But it’s space constrained. There are only so many applications you can place there. I want space enough for frequently used documents as well. Recently, I decided that I need all the space on the screen. So my task bar is on auto hide, and that makes the quick launch bar a little tougher to use as well. And finally, I can’t use the quick launch bar with the keyboard. That’s important.

So I switched to the pinned menus on the Start Menu.

StartMenu

This works better with the keyboard. I access Word, I just type the Ctrl-Esc, W. Excel: Ctrl-Esc, E. But I run short of letters soon. I have trouble between Powerpoint and processing, for instance. And I can’t store documents.

I tried Enso Launcher and Launchy, both of which are great products, but I just can’t stand the thought of them hogging up all the memory that they do. Launchy in particular.

Given that I almost always have one or two command prompts open, I write my own little tool to do the job now. It’s a command line launcher I’ve written in Perl. I call it “o”. At the first run, it indexes my hard disk. (Well, not all of it. I’ve picked what I need.) Now, if I want to read Harry Potter and the Deathly Hallows, I just type:

> o harry potter hallows

If I wanted to pick a Harry Potter book, I could:

> o harry potter
    0: D:/Entertainment/Books/Hugo Awards/2001 - J K Rowling - Harry Potter and the Goblet Of Fire.rar
    1: D:/Entertainment/Books/J K Rowling.1.Harry Potter and The Sorcerer's Stone.pdf
    2: D:/Entertainment/Books/J K Rowling.2.Harry Potter and The Chamber of Secrets.pdf
    3: D:/Entertainment/Books/J K Rowling.3.Harry Potter and The Prisoner of Azkaban.pdf
    4: D:/Entertainment/Books/J K Rowling.4.Harry Potter and The Goblet of Fire.doc
    5: D:/Entertainment/Books/J K Rowling.5.Harry Potter and the Order of the Phoenix.pdf
    6: D:/Entertainment/Books/J K Rowling.6.Harry Potter and the Half-Blood Prince.pdf
    7: D:/Entertainment/Books/J K Rowling.7.Harry Potter and the Deathly Hallows.pdf
    8: D:/Entertainment/Books/J K Rowling.The Harry Potter Encyclopedia.doc
    9: D:/My Pictures/2005-06 London/2005-07-16 06 Waterstones Oxford Street Harry Potter release.JPG
    ... more
> (0-9, q, any word): prince
D:/Entertainment/Books/J K Rowling.6.Harry Potter and the Half-Blood Prince.pdf

The program lists the files matching the words I typed, and lets me filter within that.

I just wrote this yesterday, and already, I’ve used it dozens of times. Here’s the source.

PS: While I was at it, I downloaded a Flickr uploader for Perl. So I can now upload images with the command line. This easily saves me at least 5 minutes per article.

Illegally in Germany

In October 1997, Ram, my manager at IBM, strolled over to my desk and asked if I would like to visit the US. I’d never been there before. The impulse was to say “Yes”. But…

I’d written the CAT exam once before. Didn’t get through. Applied once again. But thanks to my diligence, I’d given the wrong residence address, and never got my admission card, and didn’t bother following it up. This would be my third “attempt”. And I didn’t want to goof it up again. (I didn’t get through that one either, as it turned out.)

“Ram, I need to be back on Dec 11th.”

“Mmm… I think we should be back by then.”

“NO MATTER WHAT!”

He smiled, and said “OK. We’ll be back by Dec 11th NO MATTER WHAT.” He thought I was going to get married or something.


It was quite warm in Bangalore, so I set out with a T-shirt and formal trousers. As I was leaving, my landlord and landlady (very nice people, and in retrospect, very far-sighted) pulled me in and said, “Have some snacks. You’ll feel hungry on the way.”

I tried my protests. They’ll feed me on the plane. I’m already carrying some food. I have cash to buy stuff. I’m fat and dieting. Didn’t matter. I still ended up carrying a fairly hefty package. “And this is for Kallol.” Another package. A colleague travelling with me was an ex-roommate as well. I just hoped I wouldn’t exceed 27 kgs.

It was a KLM flight that would halt at Amsterdam. We were to land early morning in Amsterdam, take a connecting flight to Boston, and then over to Charlotte. We’d reach Charlotte by night, in time for the class next day.

The flight itself was uneventful, except for my first non-vegetarian bite.

And then the fun began.

Breakfast was done by around 5:00am local time. The captain announced that we were near Amsterdam, fasten your seatbelts.

5:30am. No landing.

6:00am. No landing. When I pulled the shutters up, we were still flying over clouds.

7:00am. No landing.

7:30am. The captain announces that due to bad weather at Amsterdam, we would not be able to land there. We were being diverted to Cologne.

Not having been on any long-haul flights before, I wasn’t even worried. It was a KLM connecting flight. KLM would do something. But for feeling a bit hungry, things were fine.

At around 11:00am, the plane began its descent. We were amidst clouds, though. For quite a while… and the plane kept descending…

Until, all of a sudden, I could see the ground about 20 feet from the plane! The fog dense enough to be indistinguishable from clouds. (Or at least, I couldn’t tell the difference.) Lucky the pilot managed to land, and I’m surprised he even tried.

8:00am. We’re still in the plane, waiting.

9:00am. Hungry. No one has told us anything yet.

9:30am. We’re all asked to get down. Delighted, we all got off, ready to board the next plane…

… only to be herded off into a glass building on the terminal, where our luggage was waiting for us. No problem. Pick up luggage. Wait.

10:00am. All the flight staff had cleared the terminal. And, looking out of the glass walls, we could see our plane taking off! There was a fair bit of confusion (and mild panic) in the room, but being the suave software engineers that we were, we stay put and relaxed.

11:00am. Still in the glass building. No flight has landed or taken off. Worse, no human in sight. I mean it: not a single human in sight other than us KLM passengers in this deserted terminal. We’re still hungry.

12:00noon. My snacks finally come out. We all have a bite. That turned out to be our lunch.

12:30pm. Some official enters the building and is mobbed. The closest we could get to him (or her?) was about 50m behind many hundreds of raised heads.

12:45pm. Official vanishes. We ask around if anyone knows more than we do. No one seems to.

1:30pm. Another official enters. Vanishes after a few minutes.

2:00pm. Finally, word gets around that we’ll be travelling via bus to Amsterdam. Clearly we’d missed our connecting flight. We’d be put in to the same flight the next day.

2:10pm. We hear a lot of activity. People start streaming out of the building. We try to join in the rush.

2:20pm. Ahead of us, we see a guy checking passports. Now, none of us had a German visa. Presumably it was OK, but in any case, we were entering Germany without a valid visa. The official stamped my passport without question.

2:30pm. We exit the airport. The temperature was 0 degrees C. I was still in my T-shirt. My warm clothes were packed. That day, I learnt two lessons. One, never keep all your warm clothes inaccessibly in the check-in baggage. (I had my check-in baggage. But it was packed, and if I opened it, I can’t put it back in. Besides, we were being herded into a bus: not much chance of hanging around to open a suitcase.) Two, it’s actually possible to get a headache from the cold. For 15 freezing minutes, we stood on the road waiting for the bus, and enjoying the pleasures of our first day on European soil.

2:45pm. Bus arrives. Mob tries to enter bus. Half of our group manages to get through. I am left behind. Fortunately, next bus is only 5 minutes behind.

7:00pm. Bus finally arrives at Schipol airport. We’re herded out to the KLM counter. By now, it’s been well over 24 hours since my last full meal.

7:30pm. We’re told we’ll get a hotel to stay in, and our flight is confirmed for the next day. At this point, we’re famished. So we exchanged some currency, and decided to buy some food. I picked a green apple. This happened to be my first green apple. No one had told me that apples could taste sour. (While on that topic, I must mention apple pies. I love apple pies in India. I hate apple pies in London. I suspect it’s the red versus green apples.)

7:31pm. I take one bite. Another bite. Have a funny feeling in my stomach. Burning sensation. And at that point, I collapsed. Physically. Just dropped on the floor and had to be pulled up.

8:00pm. Finally reach the hotel. Not entirely sure how. I’m too tired for anything but milk, so I get a glassful and go to sleep.


PS: We finally reached Charlotte a day late. Fortunately, we didn’t miss much.

Apparantly, most passengers on the flight complained to KLM and received gifts / free miles of a substantial magnitude. We didn’t know of that till much later.

This remains my only trip to Germany till date. My passport still holds an entry stamp without a visa.

We did get the bonus of spending half a day in Amsterdam, which is a rather nice place. Again, without a visa.

In search of a good editor

It’s amazing how hard it is to get a good programming editor. I’ve played around with more editors/IDEs than I care to remember: e Notepad++ NoteTab SciTE Crimson Editor Komodo Eclipse Aptana

There are four features that are critical to me.

  • Syntax highlighting. Over time, I’ve found this to increase readability dramatically. Look at this piece of code with and without syntax highlighting:
    Syntax Highlighting
    Doesn’t the structure of the document just jump out with syntax highlighting? Anyway, I’ve gotten used to that.
  • Column editing. I want to be able to do this:
    Column Editing
    Being able to type across rows is incredibly useful. I use it both for programming as well as to complement data-processing on Excel.
  • Unicode support. I often work with non-ASCII files, particularly in Tamil. Unicode support comes in handy when debugging pages for my songs site.
  • Auto-completion. This is 10 times more productive than having to look up the manual for each function.
    AutoCompletion

(Oh, and it’s got to be free too. Except for e Text Editor, all the others qualify.)

The problem is, none of the browsers that I’ve looked at support all of these features.

Editor Syntax highlighting Column editing Unicode support Auto-completion
e Text Editor Yes Yes No Yes
Crimson Editor Yes Yes No No
Notepad++ Yes No Yes No
NoteTab-Lite No No No No
SciTE Yes No Yes Yes
TextPad Yes No Yes No
UltraEdit Yes No No ?
Aptana Yes No Yes Yes
Eclipse Yes No Yes Yes
Komodo Yes No Yes Yes

Wikipedia has a more in-depth comparison of text editors.

Actually, there’s another parameter that’s pretty important: responsiveness. When I type something, I want to see it on the screen. Right that millisecond. With some of the features added by these editors, there’s so much bloat that it often takes up to one second between the keypress and the refresh. That’s just not OK.

I’ve settled on Crimson Editor as my default editor these days, simply because it’s quick and has column editing. (Column editing on e Text Editor is a bit harder to use.) When I am writing Unicode, I switch over to Notepad++. For large programs, I’m leaning towards Komodo right now, largely because Eclipse is bloated and Aptana was slow. (Komodo is slow too. Maybe I’ll switch back.)

There’s many other things on my “would love to have” features, like regular-expression search and replace, line sorting, code folding, brace matching, word wrapping, etc. Most of those, though, are either not too important, or most browsers already have them.

Well, there’s the sad thing. I’ve been hunting for a good text editor for over 10 years now. May someone write a lightweight IDE with column editing.

JPath – XPath for Javascript

XPath is a neat way of navigating deep XML structures. It’s like using a directory structure. /table//td gets all the TDs somewhere below TABLE.

Usually, you don’t need this sort of a thing for data structures, particularly in JavaScript. Something like table.td would already work. But sometimes, it does help to have something like XPath even for data structures, so I built a simple XPath-like processor for Javascript called JPath.

Here are some examples of how it would work:

jpath(context, “para”) returns context.para
jpath(context, “*”) returns all values of context (for both arrays and objects)
jpath(context, “para[0]”) returns context.para[0]
jpath(context, “para[last()]”) returns context.para[context.para.length]
jpath(context, “*/para”) returns context[all children].para
jpath(context, “/doc/chapter[5]/section[2]”) returns context.doc.chapter[5].section[2]
jpath(context, “chapter//para”) returns all para elements inside context.chapter
jpath(context, “//para”) returns all para elements inside context
jpath(context, “//olist/item”) returns all olist.item elements inside context
jpath(context, “.”) returns the context
jpath(context, “.//para”) same as //para
jpath(context, “//para/..”) returns the parent of all para elements inside context

Some caveats:

  • This is an implementation of the abbreviated syntax of XPath. You can’t use axis::nodetest
  • No functions are supported other than last()
  • Only node name tests are allowed, no nodetype tests. So you can’t do text() and node()
  • Indices are zero-based, not 1-based

There are a couple of reasons why this sort of thing is useful.

  • Extracting attributes deep down. Suppose you had an array of arrays, and you wanted the first element of each array.
    Column Selection
    You could do this the long way:
    for (var list=[], i=0; i < data.length; i++) {
        list.push(data[i][0]);
    }
    

    ... or the short way:

    $.map(data, function(v) {
        return v[1];
    })

    But the best would be something like:

    jpath(data, "//1")
    
  • Ragged data structures. Take for example the results from Google's AJAX feed API.
    {"responseData": {
     "feed": {
      "title": "Digg",
      "link": "http://digg.com/",
      "author": "",
      "description": "Digg",
      "type": "rss20",
      "entries": [
       {
        "title": "The Pirate Bay Moves Servers to Egypt Due to Copyright Laws",
        "link": "http://digg.com/tech_news/The_Pirate_Bay_Moves_Servers_to_Egypt_Due_to_Copyright_Laws",
        "author": "",
        "publishedDate": "Mon, 31 Mar 2008 23:13:33 -0700",
        "contentSnippet": "Due to the new copyright legislation that are going ...",
        "content": "Due to the new copyright legislation that are going to take...",
        "categories": [
        ]
       },
       {
        "title": "Millions Dead/Dying in Recent Mass-Rick-Rolling by YouTube.",
        "link": "http://digg.com/comedy/Millions_Dead_Dying_in_Recent_Mass_Rick_Rolling_by_YouTube",
        "author": "",
        "publishedDate": "Mon, 31 Mar 2008 22:53:30 -0700",
        "contentSnippet": "Click on any \u0022Featured Videos\u0022. When will the insanity stop?",
        "content": "Click on any \u0022Featured Videos\u0022. When will the insanity stop?",
        "categories": [
        ]
       },
       ...
      ]
     }
    }
    , "responseDetails": null, "responseStatus": 200}
    

    If you wanted all the title entries, including the feed title, the choice is between:

    var titles = [ result.feed.title ];
    for (var i=0, l=result.feed.entries.length; i<l; i++) {
        titles.push(result.feed.entries[i].title;
    }
    

    ... versus...

    titles = jpath(result, '//title');
    

    If, further, you wanted the list of all categories at one shot, you could use:

    jpath(result, "//categories/*")
    

Automating Internet Explorer with jQuery

Most of my screen-scraping so far has been through Perl (typically WWW::Mechanize). The big problem is that it doesn’t support Javascript, which can often be an issue:

  • The content may be Javascript-based. For example, Amazon.com shows the bestseller book list only if you have Javascript enabled. So if you’re scraping the Amazon main page for the books bestseller list, you won’t get it from the static HTML.
  • The navigation may require Javascript. Instead of links or buttons in forms, you might have Javascript functions. Many pages use these, and not all of them degrade gracefully into HTML. (Try using Google Video without Javascript.)
  • The login page uses Javascript. It creates some crazy session ID, and you need Javascript to reproduce what it does.
  • You might be testing a Javascript-based web-page. This was my main problem: how do I automate testing my pages, given that I make a lot of mistakes?

There are many approaches to overcoming this. The easiest is to use Win32::IE::Mechanize, which uses Internet Explorer in the background to actually load the page and do the scraping. It’s a bit slower than scraping just the HTML, but it’ll get the job done.

Another is to use Rhino. John Resig has written env.js that mimics the browser environment, and on most simple pages, it handles the Javascript quite well.

I would rather have a hybrid of both approaches. I don’t like the WWW::Mechanize interface. I’ve gotten used to jQuery‘s rather powerful selectors and chainability. So I’ll tell you a way of using jQuery to screen-scrape offline using Python. (It doesn’t have to be Python. Perl, Ruby, Javascript… any scripting language that can use COM on Windows will work.)

Let’s take Google Video. Currently, it relies almost entirely on Javascript. The video marked in red below appears only if you have Javascript.

The left box showing the top video uses Javascript

I’d like an automated way of checking what video is on top on Google Video every hour, and save the details. Clearly a task for automation, and clearly not one for pure HTML-scraping.

I know the video’s details are stored in elements with the following IDs (thanks to XPath checker):

ID What’s there
hs_title_link Link to the video
hs_duration_date Duration and date
hs_ratings Ratings. The stars indicate the rating and the span.Votes element inside it has the number of people who rated it.
hs_site The site that hosts the video
hs_description Short description

So I could do the following on Win32::IE::Mechanize.

use Win32::IE::Mechanize;
my $ie = Win32::IE::Mechanize->new( visible => 1 );
$ie->get("http://video.google.com/");
my @links = $ie->links
# ... then what?

I could go through each link to extract the hs_title_link, but there’s no way to get the other stuff.

Instead, we could take advantage of a couple of facts:

  • Internet Explorer exposes a COM interface. That’s what Win32::IE::Mechanize uses. You can use it in any scripting language (Perl, Ruby, Javascript, …) on Windows to control IE.
  • You can load jQuery on to any page. Just add a <script> tag pointing to jQuery. Then, you can call jQuery from the scripting language!

Let’s take this step by step. This Python program opens IE, loads Google Video and prints the text.

# Start Internet Explorer
import win32com.client
ie = win32com.client.Dispatch("InternetExplorer.Application")
 
# Display IE, so you'll know what's happening
ie.visible = 1
 
# Go to Google Video
ie.navigate("http://video.google.com/")
 
# Wait till the page is loaded
from time import sleep
while ie.Busy: sleep(0.2)
 
# Print the contents
# Watch out for Unicode
print ie.document.body.innertext.encode("utf-8")

The next step is to add jQuery to the Google Video page.

# Add the jQuery script to the browser
def addJQuery(browser,
    url="http://jqueryjs.googlecode.com/files/jquery-1.2.4.js"
 
    document = browser.document
    window = document.parentWindow
    head = document.getElementsByTagName("head")[0]
    script = document.createElement("script")
    script.type = "text/javascript"
    script.src = url
    head.appendChild(script)
    while not window.jQuery: sleep(0.1)
    return window.jQuery
 
jQuery = addJQuery(ie)

Now the variable jQuery contains the Javascript jQuery object. From here on, you can hardly tell if you’re working in Javascript or Python. Below are the expressions (in Python!) to get the video’s details.

# Video title: "McCain's YouTube Problem ..."
jQuery("#hs_title_link").text()
 
# Title link: '/videoplay?docid=1750591377151076231'
jQuery("#hs_title_link").attr("href")
 
# Duration and date: '3 min - May 18, 2008 - '
jQuery("#hs_duration_date").text()
 
# Rating: 5.0
jQuery("#hs_ratings img").length
 
# Number of ratings '(8,288 Ratings) '
jQuery("#hs_ratings span.Votes").text()
 
# Site: 'Watch this video on youtube.com'
jQuery("#hs_site").text()
 
# Video description
jQuery("#hs_description").text()

This wouldn’t have worked out as neatly in Perl, simply because you’d need to use -> instead of . (dot). With Python (and with Ruby and Javascript on cscript), you can almost cut-and-paste jQuery code.

If you want to click on the top video link, use:

jQuery("#hs_title_link").get(0).click()

In addition, you can use the keyboard as well. If you want to type username TAB password, use this:

shell = win32com.client.Dispatch("WScript.Shell")
shell.sendkeys("username{TAB}password")

You can use any of the arrow keys, control keys, etc. Refer to the SendKeys Method on MSDN.

Statistically improbable phrases on Google AppEngine

I read about Google AppEngine early this morning, and applied for an invite. Google’s issuing beta invites to the first 10,000 users. I was pretty convinced I wasn’t among those, but turns out I was lucky.

AppEngine lets you write web apps that Google hosts. People have been highlighting that it give you access to the Google File System and BigTable for the first time. But to me, that isn’t a big deal. (I’m not too worried about reliability, and MySQL / flat files work perfectly well for me as a data store.)

What’s more interesting unlike Amazon’s EC2 and S3, this is free up to a certain quota. And you get a fair bit of processing power and bandwidth for free. One of the reasons I’ve held back on creating some apps was simply because it would take away too much bandwidth / CPU cycles from my site. (I’ve had this problem before.) Google quota is 10 GB of bandwidth per day (which is about 30 times what my site uses). And this is on Google’s incredibly fast servers It also offers 200 million megacycles a day. That’s like a dedicated 2.3 GHz processor (200 million megacycles = 200,000 GHz x 1 second ~ 2.3 GHz x 86,400 seconds/day) — better, because this is the average capacity, not peak capacity. The only restriction that really worries me is that only 3 apps are allowed per developer.

So I decided to give a shot at publishing some code I’d kept in reserve for a long time. You may remember my statistical analysis of Calvin & Hobbes. For this, I’d created a script in Perl that could generate Statistically Improbable Phrases (SIPs) for any text. This is based on (a somewhat limited) 23MB corpus of ebooks that I had. I’d wanted to put that up on my website, but …

AppEngine only uses Python. So the first task was to get Python, and then to learn Python. The only saving grace was that I was just cutting-and-pasting most of the time. Google wasn’t helping:

Google AppEngine Over Quota Error

Anyway, the site is up. You can view it at sip.s-anand.net for now. Just type a URL, and it’ll tell you the improbable words in that site.

Visit sip.s-anand.net

Technical notes

I realise that these are statistically improbable words, not phrases. I’ll get to the phrases in a while.

The logic is simple:

  • Get the frequency of words in a corpus. I pre-generated this file. It has over 100,000 words.
  • Get the URL as text. Rather than muck around with Python, I decided to use the W3 html2txt service.
  • Convert the text to words. Splitting text into words is tricky. For now, I’m simply assuming that any group of letters is a word, and anything that’s not a letter is a word delimiter.
  • Find the relative frequency (improbability) of words. This is the frequency in the URL divided by the frequency in the corpus, normalised (i.e. scale it so that the maximum value is 1.0).
  • Create a tag cloud. I use the word frequency as the size and the improbability as the colour. You need a bit of mathematical jugglery to get the pattern right. Right now, I’m taking the 6th root of the improbability and the logarithm of the frequency to get a reasonably smooth tag cloud.

The source code is at statistically-improbable-phrases.googlecode.com.

Update: 12-Apr-2008. I’ve added some interactivity. You can play with the contrast and font size, the filter out common or infrequent words.

Update: 22-Apr-2008. Added concordance. You can click on a word and see the context in which it appears.

Firefox 3 Beta 5 crashes

I just upgraded from Firefox 3 Beta 4 to Beta 5. It’s amazing how unstable Beta 5 is compared to the earlier version. Gmail crashes. Google maps crashes. Almost every other site I visit crashes. And looks like I’m not alone: doing a Google search for “Firefox 3 beta x crash” shows a consistently increasing number of results.

Number of Google search results for Firefox 3 Beta crashes, by Beta version

Update (8/Apr/08): As the comments rightly point out, this could simply be because more people use Beta 5. Here’s the number of Google hits for “Firefox 3 Beta x” — and it shows a clear increasing trend.

Number of Google search results for Firefox 3 Beta, by Beta version

So, adjusting for this, here’s the relative crash frequency:

% of Firefox 3 Beta crash mentions on Google, by Beta version

Beta 5 still stands out.

Maybe Google search results are not a good proxy. Maybe the mention of “crash” doesn’t indicate the software itself crashing. But it sure crashes a lot more for me.

Time management

Some years ago, a friend asked me to write about how I manage my time. It seemed to him I was doing a good job of it, given that I had time to pursue my interests.

It’s something I tried to do consciously. Every few years, I used to go down the route of “time management”. I’d read stuff and try it out.

But over time, I’ve come to believe that “time” is not really “manageable”. Think about it: are most of your actions planned? Me, I just react out of habit, no matter how well planned I try to be. What I do is largely driven by what I’m in the habit of doing.

Not that time management advice is useless, but you’ll end up not following most of it. You act on a fraction of what you read. A fraction of that turns into a habit. That’s still useful. But the point is, rather than pick up 10 tips on time management, it’s more useful to pick one or two pieces of advice that you like, and are likely to act on. (You won’t do things you don’t like anyway.)

So time management is about acquiring habits that save time (and is not about reading tips that are tough to habitualise).

That begs an obvious question and a subtle one. The obvious one is what habits save time? The subtle one is why save time?

Why save time?

You’ve probably heard the phrase “time is money”. For a while, I took that statement literally. I tried to act by assigning monetary value to my time, and by doing the most profitable thing.

I was making Rs 10,000 a month at that time. That’s about Rs 50 an hour. So I figured I wouldn’t do anything that earned me less than Rs 50 an hour outside of work. I mean, if I’m making Rs 50 an hour at work, why should I make any less outside?

One small hitch. I wasn’t making any money outside of work. In fact, I was spending money. So unless I took up a night job, or started freelancing, that rule of thumb was useless. (Besides, I didn’t want to spend time outside of work working. I wanted to have fun. Watch movies, for instance.)

So I needed a different way of handling this. If I spend 3 hours at a movie for Rs 60, that could be a benchmark. If something’s more expensive than Rs 20/hour, I’d rather watch a movie. If it’s less expensive, I’d do that. Take books, for instance. A typical novel would cost Rs 180 and I’d finish it in 12 hours. At Rs 15 / hour it’s a more economical way of spending time.

Except that it doesn’t quite work that way. How much fun I had, had nothing to do with how much I paid for it.

Frankly, in daily life, I don’t think you can treat the phrase “time is money” literally. Time has nothing to do with money.

Time is like money in a different way, though. By itself, it isn’t worth much. Think about it. What can you do with money? Buy stuff you like. And if you can’t, it’s useless.

Obelix: How silly! Fancy throwing out good onion soup to make room for sesterii! Asterix: But Obelix, with sesterii, you can buy onion soup! Obelix: That's the point! Why throw out the onion soup when it was in the cauldron already?

If all you need is onion soup, why throw it out for sesterii?

Time’s like that. What can you do with time? Do stuff you like. And if you can’t, it’s useless.

There are usually two reasons people want to manage time. One is where they don’t enjoy something, and would rather spend as little time at it as possible. But look, if you don’t enjoy that stuff, time management isn’t your problem. You need to get out of your job or whatever. Managing time more efficiently is simply going to let you efficiently waste your time. (Though in the short run, that’s probably the best you can do — efficiently get rid of nuisances. I’ll talk about that shortly.)

The other reason is where they have too many (enjoyable) things to do, and can’t do all of them. But hey, if you have too much enjoyable stuff, you don’t have a problem! In a way, this is like wanting to buy many things and not having enough money. With money, you can earn more or wish for less. With time, you just have to wish for less. (Living longer may not be a practical option.) Just pick anything you like to do. Don’t regret the stuff you can’t. You only have 24 hours, and you’re among the lucky few who can fill it with things you enjoy.

So, I’m effectively saying, there’s no point trying to do things more efficiently in the long run. Picking what you do is more important than doing it efficiently. (That roughly correlates to the third habit in Stephen Covey’s Seven Habits: Put First Things First. It’s the key to time management.)


So, how do you pick what to do? You’d probably want to pick something that you like, or something that’s good for you.

But it’s tricky to predict what you like.

  • We don’t know what we want. Sometimes, it’s as simple as that — we just don’t know what we’d like to do.
  • Too much of anything… I love watching movies, but I’ve never managed to watch more than 4 a day. I’ve tried breaking that record many times. Just doesn’t work. At the end of the 4th movie, I’m sick and my bum is sore. Do I prefer movies to cleaning up? Usually. But by the end of the 4th, I’d rather clean up.
  • Preferences are not consistent. I prefer a 7 megapixel camera to a 2 megapixel one. I prefer a cheaper camera to a more expensive one. So between a $100 2MP camera and a $200 7MP camera, I’m just making a wild guess.
  • Preferences are not static. If I’m tired, I’d rather watch a movie I’ve seen before. If not, I’ll experiment with an art film. There’s no telling beforehand what my mood is going to be at any point.

It’s just as tricky to figure out what’s good for us. We have no clue what will happen tomorrow. We have no clue what consequences our actions will have. (Read The Black Swan to get a flavour of that.) So we’re really guessing and groping — though sometimes with a lot of confidence.

On the whole, it’s difficult to figure out what to pick. So what do you do?

This is completely outside the realm of time management. This is about choice. I have a few (bad) habits that guide me.

  1. Follow your moods
  2. Work less
  3. Procrastinate

Those are my principles. (But like Groucho Marx, I do have others.)

Follow your moods

There are times when people do certain things better. I’ve heard some people study best early in the morning. Others study best late at night. I don’t know if there’s any physiological benefit one way or the other, but even if it’s psychological, it makes a huge difference to study when you think you’ll learn better.

Sometimes I’m in a mood to write articles. When I do, the article usually writes itself. If not, I could spend days at it without any progress.

If there’s any reality to this, then the best thing to do is to do what you feel like doing. You’ll naturally accomplish this faster. That’s typically what I do when I’m given any work. I usually wait until I just feel like it. Then it’s usually a matter of a few hours before the job is done. Sometimes the mood doesn’t quite arrive before the deadline, in which case there’s always inspiration.

Calvin & Hobbes: Do you have an idea for your story yet? No, I'm waiting for inspiration. You can't just turn on creativity like a faucet. You have to be in the right mood. What mood is that? Last-minute panic.

Seriously: do what you feel like doing the most at the moment. That’s a great way of becoming more efficient.

In fact, I would go as far as saying, mood management is more important than time management. Moods are more precious than time. If you’re in a mood to call people, pick up the phone and talk to folks you’ve been out of touch with. That mood is rarer than the time to make calls. (At least for me, the reason I am not in touch is because I’m not in a mood — not because I don’t have time.)

Optimise that mood. Do what you’re in a mood for. And when your mood changes, go with the flow. Do a lot more of what you feel like doing. You’ll do more (which is probably good), and of what you like (which is certainly good).

Work less

I’ve talked about this in Less is more. At the end of the day, 90% of the stuff you do is useless. So why do it? Just focus on the 10%.

Procrastinate

I can’t put this better than Paul Graham’s article on procrastination.

Good procrastination is avoiding errands to do real work.

You won’t know what the important 10% until much later, so you may as well wait to find out if it’s important, and then do things.


So what am I saying?

  • Time management is about habits, not tips
  • Picking what you do is more important than doing it efficiently
  • But it’s difficult to figure out what to pick
  • So avoid doing stuff until you know it’s worth doing
  • Work when you’re in the mood — it’s faster that way

Think about it.

Reading books on a laptop

I have the habit of reading books on the screen. It’s something that started from the early 90s, when I got a copy of The MIT Guide to Lockpicking. Since I didn’t have access to a printer, I’d spent hours poring over the document on the screen. And then I discovered Project Gutenburg

I’ve heard many people ask if I have a problem with this. Personally, no. I’ve been staring at screens from the age of 12, and I’m quite used to it. My job requires me to stare at a screen for most of the day anyway. (I’m not saying there’s no a strain on the eye. My eyes are red at the end of the day. I don’t know if they would be less red if I’d been staring at paper instead of a screen. But my glasses have remained roughly the same power over ~15 years, so it’s probably not ruining my eyesight much.) For those who are like me who reads all the time and spends a lot of more time facing their laptops, you might want to check this sd card, a very good quality card that can be handy in the future.

To me, the main advantage of a book is that a book is a lot easier to handle.

  • You can fit a book into your bag, sometimes into your pocket.
  • You can hold it in your hand comfortably — it’s easy to grip, and light.
  • You can open it instantly (no need to boot up).
  • You can bookmark it (or even just remember the last page number) and quickly flip to that

None of these is possible on a computer.

Or is it?

On a desktop, I agree — it’s impossible to read for long. Your back would kill you. I’ve done it for many years, and it’s not worth the pain. With a laptop, however, you can lie down on the bed or sofa and read. It’s a huge advantage. (For just this one reason alone, I’d suggest that everyone buy a laptop.)

As for carrying books, I carry my laptop to work every day, so there’s no incremental burden. But if you weren’t doing that, it’s probably not a great idea. When I travel on weekends, I’d much rather take a physical book than a laptop. This is probably the single biggest problem with a laptop — that it doesn’t travel as easy as a book.

That’s probably offset by the advantage that a laptop isn’t really a book — it’s a library. I don’t need to decide which book to read. I can bring them all along, pick what I like, and when I’m done, move on to the next. And I’m not restricted to books. I have a fairly good collection of movie scripts and comics. Depending on how long I have on the train, and my mood, I can pick between these.

One thing that makes a laptop a lot easier to use is to rotate it.

Laptop in landscape mode

Laptop in portrait mode (rotated)

If you hold the laptop this way, it’s surprisingly easy to handle. I find that I can read this way even when standing on a crowded train — which is as much as I can expect from any book. (Strangely enough, it doesn’t seem to attract too much attention on the train either.)

If you have a decent graphics card, you can rotate your screen using the graphics properties. (I’m sure there are are hotkeys to do this. My two-year old daughter somehow knows them, and manages to turn the screen upside down in a fraction of a second, while I spend then next 5 minutes struggling to restore an upside-down screen.)

If not, you can just use a PDF reader (like FoxIt, which is better than Acrobat Reader) to rotate the page by 90°.

A laptop takes care of the problems of bookmarking and load time as well. I usually leave mine on hibernate, and it takes about 10 seconds to open up to where I left off. Sometimes I just leave the laptop on in the bag — for example if I’m changing trains.

The other solution, of course, is to try an ebook reader. Given my laptop, I haven’t tried one. But other than the ease of holding it, there’s no big I see.


The other question is, how do you find ebooks?. Other than buying them, I find that the easiest option is to search on Google. A surprisingly large number of them are indexed.

Here’s a custom search engine for ebooks.