Thursday, July 8, 2010

Tab completion in the python interpreter

Since I program mostly in python, I spend a lot of time in the default python interpreter of my distro. I even use it as a replacement for bash quite often - mainly because of python's excellent string manipulation capabilities and well, I confess, also because bash's syntax always baffles me (especially the if statements). So whenever I get stuck with some bash code, I take the escape route of opening up the python interpreter.

But the default python interpreter that comes bundled with most linux distros (and also the OS X), lacks a killer feature of bash: tab completion. One can find this feature in some python interpreters like bpython, but they sometimes overdo it (popping up suggestions even when one doesn't want them, for example).

Anyway, I recently learned from this excellent blog post by Matthias Friedrich that it is REALLY easy to add tab completion in the python interpreter: all one needs to do is import rlcompleter and readline modules of python and assign a completer key (Tab is the most natural choice, of course). The blog post I linked above also describes how to set the PYTHONSTARTUP environment variable so that tab completion is enabled every time the interpreter is opened.

Since python's readline module uses the same GNU readline utility used by bash for tab-completion, it should be just as much fun, right? Well, that's not quite the case. Because tab completion imposes a severe restriction on you here: you cannot use the Tab key for indenting your code anymore. And using single space for python's code indentation is a very bad idea: trying to distinguish between different indentation levels in heavily nested code blocks is a trouble not worth taking even for sake of the benefits given by tab completion.

Anyway, I figured out a way to circumvent the problem by looking at these lines in the source code of the rlcompleter module (The file in question is /usr/lib/python2.6/ for Debian and Ubuntu): When one presses the completion key the function complete(self, text, state) defined in line#29 is called with the word being typed as it's second argument. I simply added an extra elif after the 42nd line asking it to return '\t' if the argument consists of only whitespaces: So, now I have all the goodness of tab completion without losing the ability of using tab for code indentation!

Tuesday, July 6, 2010

Weird rounding-off bug in WebKit

I ran into this weird problem while I was writing the css for my personal website. There is a navigation bar in the page with 7 links inside a <div> sitting side-by-side:

the page rendered like this in Firefox (and for certain viewport widths in chrome)

I specified the width of the first six links to be 14% and the that of the last one 16% in the css. All the paddings, margins and borders were set to zero. So, they seven links should take up the entire width of the containing <div>, right?

Well, in webkit based browsers (I checked in Google Chrome for linux and Safari in Mac OS X leopard), that sometimes just would not happen: the total width of the seven links would fall short of the total width of the containing <div> by just a few pixels and there would be an annoying narrow strip showing the background color of the <div>.

the pesky extra pixels in Chrome

More surprisingly, on resizing the browser window, sometimes the strip would go away and sometimes it would come back again. Firefox and opera didn't have any such problem rendering the page, though.

Now, I am no specialist in web designing. But still my common sense says that as long as 6*14+16 is 100, no such strip should be there. What the hell is going on?

Luckily, I found the answer while fiddling with the excellent Developer Tools of the Chrome browser. The widths computed by Chrome were:

ElementComputed widthIntended width
Container <div>1013-
First 6 <a>'s1411013*0.14=141.82
The last <a>1621013*0.16=162.08

Yes, webkit is taking the integer parts of the floats while computing the widths of the elements, instead of rounding off properly to the nearest integer. Therefore it's no wonder that for certain values of the width of the containing <div>, the sum of the widths of the child elements isn't adding up to the width of the parent.

I later found out that this bug has been reported in WebKit Bugzilla almost 5 years ago and hasn't been resolved yet. The bugzilla page doesn't even indicate that anybody ever tried to fix this crucial flaw capable of ruining the appearance of many webpages single-handedly.

Anyway, I wrote a few lines of javascript to make sure that the site renders correctly in chrome and safari and it's working just fine. It's really annoying though, being forced to use javascript to compensate for a rendering engine's shortcoming in this era of standards-compliant browsers. I shudder to imagine what I would encounter when I finally test the site in IE.