whatspop - Kunal Anand

Hacking up Gmail macros for pagination

12/25/2007

I have spent the last few days cleaning out my Gmail with a little help from Mihais' macros. I love spelunking through email using nothing but the keyboard - it takes me back to my Stanford days when I mucked around with Pine.

Despite the shortcuts, one thing has continuously irked me about Gmail - having to use the mouse to paginate. So, I hacked up Mihai's script to do pagination from the keyboard (using 1/2). Simply copy/paste the following blocks into 'actions':

// 1: older page for all mail
49: function() {
currentPage = GrabCurrentAllMailPage();
if (currentPage >= 2) {
window.location.hash = "#all/p" + (currentPage-1);
}
},

// 2: newer page for all mail
50: function() {
currentPage = GrabCurrentAllMailPage();
if (currentPage)
{
window.location.hash = "#all/p" + (currentPage+1);
}
else
{
window.location.hash = "#all/p2";
}
}

As you can see, both of those actions depend on the following helper function:

// Check the url for a pagination link - if you see /p# extract the #
// I should get a bit smarter and check the current page to do inbox routing
function GrabCurrentAllMailPage() {
var pageArray = window.location.hash.match(/^(.*)(\/)(p)([0-9]+)(.*)$/);
// If there is no hash, or the regex fails, then test for properties
if (pageArray)
{
if (pageArray.length != 6) {
return 1;
}
else {
return parseInt(pageArray[4]);
}
}
}

I had previously used -/+ for pagination, but the - key code is 0 - which was getting in the way of deleting, which is #. Oddly, that key code is also zero. Is it because of the shift key modifier?

Note, you must be on the all mail page for this to work properly. If you hit next page from the inbox, you will be routed to page 2 of all mail. Yeah, this is a bug and the code is totally ugly, but it's Christmas and I just want to read/clean my mail.

Happy holidays to all!

List methods that handle predicates in Python

12/18/2007

In continuation of a previous post of using predicates/lambdas in Python, I prepared some helpful list methods that you can drop into your current and future Python scripts. What follows in an introduction/walk-through of the five methods. Note, when I say predicate, I am referring to a literal value or a function pointer.

Exists(predicate)
* Returns true if the predicate is satisfied by at least one list member.

FirstIndex(predicate)
* Returns the first integer position in the list that satisfies the predicate.

FirstValue(predicate)
* Returns the first value in the list that satisfies the predicate.
* Note, the returned value may be a complex object.

LastIndex(predicate)
* Returns the last integer position in the list that satisfies the predicate.

LastValue(predicate)
* Returns the last value in the list that satisfies the predicate.
* Like FirstValue, the returned value may be complex.

Bored? Here is the overloaded list, which I am dubbing 'PredicateList':

from types import FunctionType
from UserList import UserList

class PredicateList(UserList):
def Exists(self, predicate):
"""Returns true if the predicate is satisfied by at least one list member."""
if type(predicate) is FunctionType:
for item in self.data:
if predicate(item):
return True
return False
else:
return predicate in self.data

def GetIndex(self, predicate, reversed):
"""Common functionality shared by FirstIndex and LastIndex."""
xr = xrange(len(self.data))
if reversed:
xr = xr.__reversed__()
for i in xr:
try:
if type(predicate) == FunctionType:
if predicate(self.data[i]):
return i
else:
if self.data[i] == predicate:
return i
# Function predicates that check object properties will fail on simple
# types like strings. This is rather unelegant, but works.
except AttributeError:
pass
return None

def FirstIndex(self, predicate):
"""Returns the first integer position in the list that satisfies the predicate."""
return self.GetIndex(predicate, False)

def FirstValue(self, predicate):
"""Returns the first value in the list that satisfies the predicate."""
firstObjectIndex = self.FirstIndex(predicate)
if not firstObjectIndex is None:
return self.data[firstObjectIndex]
else:
return None

def LastIndex(self, predicate):
"""Returns the last integer position in the list that satisfies the predicate."""
return self.GetIndex(predicate, True)

def LastValue(self, predicate):
"""Returns the last value in the list that satisfies the predicate."""
lastObjectIndex = self.LastIndex(predicate)
if not lastObjectIndex is None:
return self.data[lastObjectIndex]
else:
return None

Note, PredicateList extends UserList (this is found under your Python installation's lib/), which happens to be a Python wrapper for the list type. If you are curious, there is also a UserDict class that acts congruently for dictionaries. As you can see, everything above is straight-forward. I am however a bit embarrassed by catching the AttributeError exception; there is certainly a better way of accomplishing that - one way that comes to mind is to do a type check prior to grabbing the property value.

Alright, with that out of the way here is an example use-case. Suppose I had a Person class that looked like the following:

class Person():
def __init__(self, firstName, lastName):
self.firstName = firstName
self.lastName = lastName
def __str__(self):
return '%s %s' % (self.firstName, self.lastName)

Now let's initialize a PredicateList and append some members. Note, I would have preferred to have simply used the [] notation, but this will have to suffice:

sampleList = PredicateList()

sampleList.append('3')
sampleList.append('2')
sampleList.append('1')
sampleList.append(Person('Joe', 'Shmoe'))
sampleList.append('5')
sampleList.append('2')

print sampleList

Now, we can use the PredicateList like so:

# Existence checks
print sampleList.Exists('2')
print sampleList.Exists(lambda x: x == '2')

# First index checks
print sampleList.FirstIndex('2')
print sampleList.FirstIndex(lambda x: x == '2')

# First object checks
print sampleList.FirstValue('2')
print sampleList.FirstValue(lambda person: person.firstName == 'Joe')

# Last index checks
print sampleList.LastIndex('2')
print sampleList.LastIndex(lambda x: x == '2')

# Last object checks
print sampleList.LastValue('2')
print sampleList.LastValue(lambda person: person.lastName == 'Shmoe')

There were things that I obviously omitted from this class. For instance, map() and filter() already take lambdas as function arguments, making operations like value casting and spawning new lists seem relatively simple.

There may be an oversight in the code above as this was a really fun 10 minute exercise with the REPL. I always appreciate feedback, so feel free to drop me a line.

An awesome Zune commercial

12/10/2007



I cannot express how much I love this clip - it's beautiful and has a great message. Whoever is heading the Zune marketing campaign at Microsoft seriously gets it. To me, this spot has much more personality than any iPod propaganda in the past few years. If you're curious, you can visit Zune Arts.

Simple predicates using lambdas in Python

12/04/2007

I have been spinning in Python for a few days now in an attempt to port some C# bits. In the C# codebase, I typically exercised the following:

List list = new List();
list.Add(PreviouslyInstantiatedType); // Imagine many populators
list.FindIndex(delegate(T) { T.someProperty == true; });

I love being able to pass in anonymous functions or function pointers around. Imagine building up a tree of nodes and returning the position in the tree where a given node's property has a specific value or a combination of values. Of course, the beauty of this relies on the underlying looping - boring stuff to constantly copy/paste throughout your code.

So as I was writing the equivalent Python, I came up with:

list = []
list.append(PreviouslyInstantiatedType)
list.index(lambda x: x.someProperty == True)

Everything looks cool - right? Well, that doesn't seem to work. It turns out that index does not seem to like functions/lambdas as evaluators.

Here is a first stab at implementing something for this. Note, I am just trying to cheaply clone C#'s list method "FindIndex" and have not checked out Python's list method "index."

def fIndex(f, list):
for i in xrange(len(list)):
if f(list[i]):
return i
return -1

This iterates through the provided list, and applies the function for every item. In this case, there should be some sort of type checking that the function is a boolean - rather than error catching.

In putting all of this together, imagine the following object and list:

class person:
def __init__(self, firstName, lastName):
self.firstName = firstName
self.lastName = lastName

people = [person('j','h'),person('k','a'),person('n','g')]

If someone asked me to print out the first position in the list where the person's last name is 'a', I would do:

print fIndex(lambda p: p.lastName == 'a', people)

This whole thing is extremely simple - but I am loving it.

About I am currently a Senior Engineer at MySpace. Feel free to check out my personal collective.

Archives
April 2005
May 2005
June 2005
July 2005
August 2005
September 2005
October 2005
November 2005
December 2005
January 2006
March 2006
April 2006
May 2006
June 2006
July 2006
August 2006
September 2006
October 2006
November 2006
January 2007
February 2007
April 2007
November 2007
December 2007
January 2008
March 2008
April 2008
May 2008
June 2008

Subscribe to my feed