Sunday, August 21, 2005


A Spotlight Lisp plugin in a day, or I never metadata I never liked

While planning my approach into CLSQL to add Fuzzy SQL, I found myself wanting to just search for keywords, Spotlight-style. Well, how hard can it be? Not that hard, as it turns out. I basically just want to throw the text of a file to Spotlight and have it index the contents. Even if you have no Objective C or Cocoa experience like me, copying and modifying code is pretty straightforward.

I started with this article on Creating Spotlight Plugins. In the info.plist, I substituted his type of "" with "com.lisp.lisp", and "lisp" as the file extension. In the schema.xml, I made a custom metata for lisp files called com_lisp_lisp_data.

The XCode project makes a file called 'GetMetaDataForFile.c', which gets renamed to 'GetMetaDataForFile.m' since we use Objective C and Cocoa. The meat of this file is a callback function called 'GetMetaDataForFile'. All I do in this function is read the entire file into a NSString and add it to the 'mutable dictionary'.

Here's the function:

Boolean GetMetadataForFile(
void* thisInterface,
CFMutableDictionaryRef attributes,
CFStringRef contentTypeUTI,
CFStringRef pathToFile)
Boolean success=NO;
NSAutoreleasePool *pool;

// Don't assume that there is an autorelease pool
//around the calling of this function.
pool = [[NSAutoreleasePool alloc] init];

/* Pull any available metadata from the file */

NSString *fileText = [NSString stringWithContentsOfFile:pathToFile];

[(NSMutableDictionary *)attributes setObject:fileText

// return YES so that the attributes are imported and
// add more resilient error handling at your own discretion

//memory management
[pool release];

return success;

Build this in XCode, then:

My-Computer:~/LispImporter/build rrc$ sudo cp -r LispImporter.mdimporter /Library/Spotlight

We start with a small lisp file:
My-Computer:~/LispImporter/build rrc$ cat ~/small.lisp
;; A small lisp file
(format t "This is a small lisp file")

Index this file:
My-Computer:~/LispImporter/build rrc$ mdimport -d1 ~/small.lisp
2005-08-21 20:41:05.624 mdimport[630] Import '/Users/rrc/small.lisp' type 'com.lisp.lisp' using 'file://localhost/Library/Spotlight/LispImporter.mdimporter/'

See what Spotlight thinks about this file. Note the 'com_lisp_lisp_data' attribute:
My-Computer:~/LispImporter/build rrc$ mdls ~/small.lisp
/Users/rrc/small.lisp -------------
com_lisp_lisp_data = ";; A small lisp file (format t "This is a small lisp file") "
kMDItemAttributeChangeDate = 2005-08-21 20:41:05 -0400
kMDItemContentCreationDate = 2005-08-21 20:37:33 -0400
kMDItemContentModificationDate = 2005-08-21 20:37:33 -0400
kMDItemContentType = "com.lisp.lisp"
kMDItemContentTypeTree = ("com.lisp.lisp", "", "public.item", "public.content")
kMDItemDisplayName = "small.lisp"
kMDItemFSContentChangeDate = 2005-08-21 20:37:33 -0400
kMDItemFSCreationDate = 2005-08-21 20:37:33 -0400
kMDItemFSCreatorCode = 0
kMDItemFSFinderFlags = 0
kMDItemFSInvisible = 0
kMDItemFSLabel = 0
kMDItemFSName = "small.lisp"
kMDItemFSNodeCount = 0
kMDItemFSOwnerGroupID = 501
kMDItemFSOwnerUserID = 501
kMDItemFSSize = 60
kMDItemFSTypeCode = 0
kMDItemID = 1604367
kMDItemKind = "Document"
kMDItemLastUsedDate = 2005-08-21 20:37:33 -0400
kMDItemUsedDates = (2005-08-21 20:37:33 -0400)

Great! Now tell Spotlight to do all the lisp files:
My-Computer:~/LispImporter/build rrc$ mdimport -r /Library/Spotlight/LispImporter.mdimporter
2005-08-21 20:43:47.750 mdimport[633] Asking server to reimport files with UTIs: ("dyn.ah62d4rv4gk8y2wnxna", "dyn.ah62d4rv4ge8024pxsa", "com.lisp.lisp")

Go away for a while...
Then give it a try.

Richard, spotlight already seems to be indexing my .lisp files. Maybe because I have MCL and LispWorks and ACL installed and one or more of them informs the OS that the .lisp extension is a subclass of text file?
Otherwise, it'd be nice to see the plugin up on the Web somewhere!

It could be that one of those apps did some Spotlight stuff; when I was reading about this, some people were adding other built-in types (for python, php, etc.) to the SourceCodeImporter's plist. Others were warning that this wasn't a good idea.

A way to check is go to terminal and run the mdls command, for example

mdls small.lisp

and look at the kMDItemContentTypeTree attribute. With my importer, for this file it's
("com.lisp.lisp", "", "public.item", "public.content").


I didn't put it on the web because I don't have web space, my code was just cut & pasted from other sources and I don't know that much about Objective C so it could be buggy. I'll mail you my XCode project, source & binary for you to peruse.
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?