clearInterval() workaround for some Android browsers

Speedy is written with Cordova, using HTML and Javascript to create an installable (and sellable) Andorid app. Cordova uses the Android browser to render the appliation, which in general works quite well. However, I ran into a problem on some devices with window.clearTimeout(), and it took me a while to work around it.

At its core, Speedy is just a function that runs every so often to display some text. The idiomatic way to do this in Javascript is with setInterval(). In the simplest case, you'd use it like this:

var intervalId = window.setInterval(function(){console.log("Hi")}, 1000);

When you want to cancel the interval, you'd use cancelInterval():

window.cancelInterval(intervalId);

This all works fine, even on the 'problem' browsers. In fact, moving back to this simpler usage ended up being the solution to my problem.

Because I'm using Angular, I decided to make a somewhat more idiomatic wrapper for setInterval():

function $interval(fn, ms){
    var t = window.setInterval(function(){$scope.$apply(fn)}, ms);
    return function(){ window.clearInterval(t)};
}

...

var stop = $interval(function(){console.log('Hi')}, 1000);

...

stop();

To me this nicely encapsulates the set/clearInterval() calls. It works in desktop browsers, on my Nexus 4, and even on my ancient Huawei 8150 running Android 2.3. It failed on my Samsung Galaxy S running 4.2.2, and I had reports of it failing on an HTC One S running 4.1.1 and on an HP tablet.

I haven't precisely tracked down the issue, but it seems that the function returned by $interval is failing to properly close over t. In any case, the solution was to return the interval id, rathern than a function, and pass it to window.cancelInterval() when required.

On a related note, as part of my testing I found that Angular's $timeout() (which wraps window.setTimeout()) also does not work on some Android browsers. Even worse than with setInterval(), $timeout() never starts at all. I'm not sure if this is an issue with closures in general (although I use them elsewhere in the codebase), or if somehow interval/timeout are particularly sensitive to being wrapped.


Advanced Mercurial

I've been using Mercurial for roughly 3 years. By and large the basic pull/push/branch/merge/commit commands have done everything I've needed. Lately I've been feeling a little constrained, perhaps because git is opening my eyes to new concepts.

I had started to think that maybe Mercurial just wasn't that good. It turns out I just didn't know how to use it.

(A lot of these tips and tricks come from Steve Losh)

Secret Business

hg phase -fs

A changeset in mercurial has a phase associated with it: secret; draft; or public. A new (unpushed) commit creates a draft changeset; pushing it makes it public. This is usually all hidden away, but you can manually set the phase of you want. In particular, setting it to secret means that it will not be pushed when you push the rest of the repo. This (for example) will let you maintain a private bookmark without pushing a new head.

You can also set a new commit to secret using hg commit -s.

To make a changeset (and its ancestors) pushable again, change its phase to draft:

hg phase -d

Push like Git

hg push -r .

Mercurial uses '.' as shorthand for "the parent changeset of the working directory", ie usually the head of the branch you are on. Using -r to specify the revision to push, along with '.', means that you only push the current branch. Again, this is a way to maintain a local branch/bookmark.

Don't look stupid

hg commit --amend

Adds the changes in your working directory to the last (draft/unpushed) commit. So when you commit then see a stupid mistake, you can fix it and amend the commit. ie, no more commit -m typo

Avoid merge commits

hg rebase

Rebase takes a series of changesets and moves them to a different parent. In essence, it lets you clean up local history and avoid polluting the hg timeline with a bunch of merge commits.

Let's say you’re working on an issue on default. Once you're done, you pull and because someone else has committed to default, there's now two heads. Rather than just merge them in, you can rebase your changes on top of the other/public head:

hg rebase -m "Fixes issue 1765"

By default, rebase uses the parent of the working directory as the base, but you can specify it explicitly with -b <changeset>. You can also set the destination with -d.

Rebase starts at the “-b” revision, then works backwards until it finds a common ancestor with the destination. It takes all of the commits after that ancestor, 'replays' them as children of the destination destination changeset, then deletes the originals. Note that you might have to resolve multiple merge conflicts as hg works its way through the changesets.

If all that sounds crazy, think of it this way. If you have uncommitted changes in your working directory, pull then update (without -C), hg automatically attempts to "rebase" your uncommitted changes onto the new tip. This is just a fancy way of doing something similar with work you’ve locally committed.

Rebase is a plugin that needs to be enabled, and can only be used on draft/unpushed changesets.

Show progress

There’s a progress bundled extension for hg, which gives you a progress indicator for long-running operations. You just need to enable in [extensions] and also set verbose = False under [ui]

Shelve to change branches

hg shelve
hg unshelve

You do a bunch of work then realise you’re on the wrong branch. Often Mercurial will let you switch branches, but sometimes it can’t rebase your uncommitted changes cleanly onto the new branch.

hg shelve puts all the uncomitted changes in your working directory aside. It’s like hg update -C, except you keep a copy of your changes. hg unshelve re-applys the changes to your working directory, after you’ve done whatever else you like (pull, update, change branches etc).

Shelve is an extension that you need to enable.

Patch a changeset to another branch

hg export -o patch <revisions>
hg import patch

Lets say you commit a change on your dev branch then later realize that it needs to be on prod. You could copy it across manually, or you could create a patch. I've had bad luck creating a patch with TortoiseHg in the past, but the commandline version works perfectly. Note that this takes only the diff for the list of revisions you give it, so you need to make sure to include everything you need.

Useful Stuff

I have a bunch of random useful extensions and aliases in my mercirial.ini/hgrc:

[extensions]
purge=
rebase= 
graphlog= 
progress=
shelve=

[ui]
verbose = False

[alias]
co = commit -m
secret = phase -fs
draft = phase -d
last = log -l 5 --style compact
preview = merge --preview 
addremove = addremove -s 100
untrack = rm -Af
amend = commit --amend
nudge = push -r .
glog = glog -l 10 --template "{rev}:[{branch} {bookmakrs}] {author|user}: \"{desc}\"\n"
repull = pull --rebase

Make it look pretty

If you’re using bash (on linux or cygwin), you can make your life a lot easier by showing the current branch and bookmark in the command prompt. Add this to your .bashrc:

hg_branch() {
            hg branch 2> /dev/null 
}

hg_bookmarks() {
            hg bookmarks 2>/dev/null | awk '/\*/ {print $2}'
}

DEFAULT="\e[37;40m"
PINK="\e[35;40m"
GREEN="\e[32;40m"
ORANGE="\e[33;40m"

export PS1="\n${GREEN}\w ${ORANGE}\$(hg_branch) ${PINK}\$(hg_bookmarks)${DEFAULT}\n$ "

This will give you a prompt that looks like this:

~work/tmp default dev
$

Things to Think About

This is a continually updated colleciton of articles, talks and books that made me really stop and think, and that I want to re-visit periodically.

In Praise of Idleness - Bertrand Russell. This long article talks about idleness as the pinalce of civilization and ponders why, given our wealth, we spend so much time working. Although I take issue with a lot of his economic thinking (which given the social context was understandable), there's some thought provoking stuff here, and some lovely turns of phrase.

Solitude and Leadership - William Deresiewicz. A thoughtful lecture given at West Point about the need for space to think in order to be an effective leader, and more importantly, to lead a moral life.

How a Radical New Teaching Method Could Unleash a Generation of Geniuses - Joshua Davis. Some interesting examples of how letting kids find and follow their own interests, with minimal guidance, is a much more effective way of teaching that what we're used to.

Rich Hickey's Greatest Hits. Rich Hickey is probably my favourite thinker on programming. He is insightful, profound and entertaining. This is a list of his 5 best presentations. All of them have affected the way I think about writing code, and some, like Simple Made Easy, about how I live.

The Enchiridion - Epictetus. Of the Roman Stoics, Epictetus is the one I enjoy reading most. The Enchiridion ("handbook") is short, witty, acerbic, and deeply thought provoking. I've spent a lot of time exploring it over on This Coding Life.

The Past Didn't Go Anywhere - Utah Phillips. This spoken-word album (with ambient music from Ani DiFranco) has had a massive impact on me. Utah's stories are deeply humane. They also (in my more leftist days) openned my eyes to the anarchistic side of the Left, which in a strange way helped move me towards left-libertarianism. I listen to this whenever I feel like I need some grounding.

Antifragile - Nassim Taleb. Taleb is one of my favourite modern thinkers. Like Epictetus, he can be acerbic and arrogant, but there is a rigour and depth to his thinking that is very attractive (how many philosophical authors include an appendix of rigourous maths to back up their claims?). Much more so than Epictetus, Taleb has a large humane streak that counter-balances his arrogance. He has a writing style all of his own, which can be a good and a bad thing. Fundamentally though, he changes the way I think.

Master of many trades - Robert Twigger. An interesting article on the importance (for human happiness) of learning across multiple areas, and the dangers of over-specialization.

The Courage to be Vulnerable - Krista Tippett with Brené Brown. This is a great conversation on shame and vulnerability. Although it seems like it might be a bit TED/Oprah-y, there's some deep insight here.

The boy whose brain could unlock autism - Maia Szalavitz. This is a great article on the brain chemisty of autism. It took me a little by surprise, because I thought the standard view of austism was that it was rooted in over stimulation and hypersensitivity. I see a lot of parallels between austism and introversion, especially as discussed in Quiet: The power of introverts in a world that can't stop talking. My experience of autism with Jeremy is that it's very much like a hyper-intense form of introversion.

Civil Disobedience - Thoreau. While maybe not directly applicable to modern political life, Thoreau's views on the effectiveness and moral basis of government are interesting and thought provoking.

Clojure Programming with Hand Tools - Tim Ewald. The clojure community is big into simple tools and concepts, which is one of the main reasons I'm attracted to the language. This talk draws a parallel between woodworking with simple hand tools and programming with clojure. It makes me want to get into clojure even more, but also makes me want to get into woodwork. Very inspiring.

Reaching My Autistic Son Through Disney - Ron Suskind. A touching a somewhat confronting story about an austic boy learning to understand his world through the characters, particularly side-kicks, in Disney films. Although Jeremy is nowhere near this level on the spectrum, a lot of it rang true. It was a great reminder that, although he can't always express it clearly, Jer is intensely sensitive to what happens around him.