Archive for December, 2004

Clueless & Accurate Criticism of ReSTedit

Friday, December 31st, 2004

Stain seemed to be rather focused on trying to be as negative as possible in his reaction to ReSTedit.

I like the idea, but the result is useless. The “Render” button is slow, Auto Update isn’t Auto, and for some reason the rendered text is fucked up with characters being way to high.

See for example

I like the claim that the render button is slow. Not only is it slow, it isn’t hooked up at all! Neither is the Auto Update checkbox. The only rendering the app does is via the Auto Update timer, which he claimed didn’t work. That is pretty funny.

Now, as far as his claim that the output is rather fugly. Yup. Absolutely right. Sucks, doesn’t it.

So fix it and send me some new CSS! I tried and was tortured by the tools used to edit CSS (that, and I suck at web page design anyway).

The output format is entirely controlled by a CSS file found within the app wrapper. It is the same CSS that is provided in the docutils project source. Fix up that CSS and the rendered documents will look much better.

Update: I have added a toolbar item that allows you to quickly swap between style sheets. It is populated with any style sheets found in ~/Library/Application Support/ReSTedit and in the app’s wrapper.

This link leads to the current CSS style sheet used by docutils (and, hence, ReSTedit). Save it into the above directory and edit away!

And, of course, if anyone comes up with a decent style sheet or two, I’ll quite happily add it into the ReSTedit source.

ReSTedit now renders MarkDown

Thursday, December 30th, 2004

Dale Gillard pontificated in the original ReSTedit 0.50 release posting about wanting an application like ReSTedit that supports Gruber’s MarkDown.

As it turns out, it was trivial to add support for such to ReSTedit and doing so lays the foundation for different kinds of docutils output– HTML without CSS, PDF, etc..– that has been on the TODO list since the project was started.

The current ReSTedit top-of-tree contains support for MarkDown. There is now a pop-up button on the toolbar that can be toggled between ReST and MarkDown. As soon as it changes, the content on the left is re-rendered using whatever markup language has been selected.

ReStructured Text seems to be a superset of MarkDown; I don’t really see anything in MarkDown that can’t be done in ReStructured Text nearly as conveniently. From my brief play, I’m not sure why there was a need for MarkDown as opposed to simply using docutils & ReStructured Text directly. It is quite convenient that MarkDown can produce document fragments, but it would not be hard to patch docutils to do exactly that.

In any case, if you want to build a version of ReSTedit that supports MarkDown (on Panther), then:

– download and install PyObjC 1.2

– download and install docutils 0.3.8 (package on my file sharing page)

– grab the source from here (you can mount that URL in the Finder or use ‘svn checkout’)

– cd into the restedit source and python py2app

The built app will be found in the dist/ directory.

PyObjC 1.2 Released

Wednesday, December 29th, 2004

PyObjC PyObjC v1.2 is now available. You can grab it from the sourceforge download page or from my idisk.

The major changes are listed below. There is some seriously cool stuff in here; new packaging, support for pure-python loadable NSBundles, categories, better bridging of complex types, and revamped examples.

  • PyObjCTools.AppHelper.stopEventLoop will attempt to stop the current
    NSRunLoop (if started by runConsoleEventLoop) or terminate the
    current NSApplication (which may or may not have been started by
  • This version no longer support Python 2.2. Python 2.3 or later is
  • It is now possible to use reload on modules containing Objective-C
  • objc.loadBundle now returns bundle we just loaded.
  • Added objc.loadBundleVariables and objc.loadBundleFunctions,
    two functions for reading global variables and functions from a bundle.
  • objc.runtime will now raise AttributeError instead of objc.nosuchclass_error
    when a class is not found.
  • objc.Category can be used to define categories on existing classes:
    class NSObject (objc.Category(NSObject)):
        def myMethod(self):

    This adds method myMethod to class NSObject.

  • py2app is now used for all Example scripts and is the recommended method
    for creating PyObjC applications.
  • Proxies of dict, list, and tuple now respect the invariant that you should
    get an identical instance if you ask for the same thing twice and the
    collection has not been mutated. This fixes some problems with binary
    plist serialization, and potentially some edge cases elsewhere.
  • There is now a __bundle_hack__ class attribute that will cause the PyObjC
    class builder to use a statically allocated class wrapper if one is
    available via certain environment variables. This functionality is used
    to enable +[NSBundle bundleForClass:] to work for exactly one class from
    a py2app-created plugin bundle.
  • We now have a working Interface Builder palette example due to
  • bool(NSNull.null()) is now false.
  • supports several new commands:
    * build_libffi
      builds libffi (used by build_ext)
    * build_html
      builds html documentation from ReST source
    * bdist_dmg
      creates a disk image with the binary installer
    * bdist_mpkg
      creates a binary installer
    * test
      runs unit test suite (replaces Scripts/runPyObjCTests
      and Scripts/runalltests)
  • PyObjCStrBridgeWarning can now be generated when Python str objects
    cross the bridge by calling objc.setStrBridgeEnabled(False). It is
    HIGHLY recommended that your application never send str objects over
    the bridge, as it is likely to cause problems due to the required
    coercion to unicode.
  • The coercion bridge from Python to Objective-C instances can now be
    augmented from Python as it is exposed by OC_PythonObject. See
    objc._bridges. This is how the str -> unicode -> NSString
    bridge with optional warnings is implemented.
  • The coercion bridge between Python objects and Objective-C structures
    can now be augmented from Python as it is exposed by OC_PythonObject.
    See objc._bridges. This is how the Carbon.File.FSRef
    <-> '{FSRef=[80c]}' structure bridge is implemented.
  • Extension modules such as _objc, _AppKit, etc. are now inside
    packages as objc._objc, AppKit._AppKit, etc. They should never be
    used directly, so this should not break user code.

ReSTedit 0.50 Available

Wednesday, December 29th, 2004


A build of ReSTedit 0.50 is available on my .mac file download page. It should “just work” on any Mac OS X 10.3 system as it includes both the pyobjc and docutils libraries within the app wrapper.

Beyond a handful of bug fixes, ReSTedit includes new features described in this post.

The README and ToDo list have also been updated.

Removing duplicate files

Wednesday, December 29th, 2004

My sister received a new powerbook for Christmas and I’m in the process of moving her world from an old iMac to the new powerbook. I chose not to use the automatic migration tool because there are several years of garbage strewn across the old system’s hard drive.

Somehow, my sister managed to duplicate a huge number of the thousands of digital photos in her iPhoto library. Some are duped many times and there were a number of copies of the photo library from various efforts to back it up. Worse, some of the “backups” had photos that weren’t in the other libraries.

I needed something that could detect and remove duplicate files found within any random directory. I couldn’t find a freeware tool that would work without lots of user interaction or did the dupe test in a fashion that I found reasonable.

So, I wrote a python script that does what I need. Maybe others will find it useful.

The latest version can be found at It is a one-off that solved a problem, not an attempt to write the world’s best python script.

It works by:

  • launched via command line by passing a set of directories to be scanned
  • traverses all directories and groups all files by size
  • scans all sets of files of one size and checksums (md5) the first 1024 bytes
  • for all files that have the same checksum for the first 1024 bytes, checksums the whole file and collects together all real duplicates
  • deletes all duplicates of any one file, leaving the first encountered file as the one remaining copy

It is acceptably fast, processing 3.3 gigabytes of random files in only a few minutes (removing 1.2 gigabytes of duplicate files).

KQueue; nothing is ever as simple as assumed.

Tuesday, December 28th, 2004


Over vacation, I have recreationally hacked upon ReSTedit. In particular, I wanted to add two features that have been on the todo list since the project’s inception.

First, the toolbar has always had a segmented control that indicates whether both the source and rendered views were visible or which one was visible in the case where the vertical split view was fully expanded or collapsed.

It was totally useless. The original intention was to allow the user to click on one of the segments to pop the split view to a particular position, as appropriate.

Unfortunately, NSSplitView does not have API to tightly control the position of the split. Rainer Brockerhoff wrote a replacement for NSplitView called RBSplitView that does provide programatic control over the split.

Once I figured out how to plug the views into RBSplitView, it all just works. The real challenge was mostly of my own creation. RBSplitView is really designed to work via instantiation from an IB palette. I chose to configure it from my code because I didn’t want to have the palette around to edit the NIB and I eventually want to add some dynamic UI behavior.

Now, the reason why I wanted the above feature was for the second feature. Long ago, I added Uli’s UKKQueue class to the project. The intention was to monitor any opened files and automatically re-render the ReStructured Text whenever a file is changed on disk.

I never got around to implementing the feature because I assumed it would be more challenging than it appeared and I didn’t have the time to go off and figure out what the hell was going on if something break.

That particular assumption proved to be very accurate.

KQueue’s work by monitoring a particular open file for various events like delete, rename, write, attributes changed, or the like.

My initial naive implementation optimistically assumed that I could monitor the file for WRITE events and respond by reverting the document.

That didn’t work. As a matter of fact, it broke in different ways depending on which app the file was saved within. For emacs, you might see a delete event or a rename event depending on if a backup file is created or not. This also means that NSDocument will sometimes follow the file to the backup; that is, you’ll end up editing ‘foo.txt~’ instead of ‘foo.txt’. For TextEdit, it is a slightly different sequence of events.

All in all, it required quite a bit of head scratching and ‘print’ style debugging to figure out what the hell was really going on with each editor. I think I have a relatively complete solution now. Of course, then there was the little problem of leaking open file descriptors.

In the end, I watch for WRITE, DELETE, RENAME or EXTEND events. If any are received, I revert the document (and warn the user if there are unsaved changes that might be lost).

All of the code can be found in the ReSTedit SVN repository. contains all of the kqueue related code beyond the very simple bridge code found in contains all of the code related to the RBSplitView configuration and interaction.

Mickey’s Twice Upon a Christmas

Friday, December 24th, 2004

I just watched a DVD of Mickey’s Twice Upon a Christmas. I had no background on the film and the animation style really caught my eye. In particular, the film is entirely 3D computer animation that is radically different from traditional Mickey cartoons. It looks very much like it is a seriously upgraded version of the same technology to do Rollie Pollie Ollie.

The quality of the rendering is quite good, though it totally lacks in any atmospheric lighting or effects beyond very basic localized stuff. In general, the lighting and shadows do not create any coherent set of light sources. Textures tend to be extremely simple and flat. Whether that is a limitation of the technology used or a result of artistic direction is unclear. Certainly, Mickey cartoons tended to be relatively untextured.

At the same time, the actual animation is quite good. The facial expressions are quite lively and there is some limited movement of fabric. In general, the stories are quite well told given the rather traditional nature of Mickey related cartoons.

I wonder if the same animation group within Disney will be doing Toy Story 3. There are aspects of the Mickey DVD’s animation stylings that would lend themselves well to creating a Toy Story like animation. If it is, then Disney clearly has a bunch of work to do achieve look and feel cohesiveness between TS2 and what will be TS3, but they are well on their way. It looks like Toy Story 3 will largely be a question of whether or not Disney can create and present a good story. I wonder if Pixar already had a TS3 story line roughed out?

Toy Story 3 certainly will be interesting.

Sing back if the FCC lifts cell phone ban on planes

Monday, December 20th, 2004

As is being reported all over the place, the FCC is considering lifting the ban on cell phone use on airplanes.

Air travel already sucks and it the ongoing, ineffective, “security theater” that we all have to go through to get to a miserable flight isn’t improving things.

Adding in loud talking idiots on cell phones during a flight pretty much takes the cake. I could easily envision a little spot in hell that involves spending eternity in a middle seat eating airplane food with two loud cell phone users having an inane conversation on either side.

If the FCC does lift the ban, how should those of us offended by loud cellers respond?

If a polite “please keep it to yourself” or “dude, I’m trying to sleep” doesn’t work, I’m thinking that a rousing round of “Mary had a Little Lamb” or “Jingle Bells” will do the trick.

If we can’t dance in protest, we can certainly sing.

Followup on World’s Most Annoying P2P

Saturday, December 18th, 2004

A couple of people pontificated on my original post that I didn’t get the point that the author was trying to make.

I most assuredly did get the point. I’m fully aware of the T-Shirt love-in that was the result of the DeCSS obfuscated code product and I thought it was both quite cool and quite effectively made the point it was trying to make.

Neat. Made a bit of a media splash and the response was generally ‘wow, they are trying to claim that that is rocket science protection technology?’. And it created a bunch of geek shirt / political activist combo paraphernalia.

But DeCSS is a different beast than P2P. CSS is a standard that an entire industry adopted. DeCSS effectively made that standard available to markets that could not otherwise consume CSS protected media.

P2P is not a standard. It is not a locked up technology that “BigCo” is trying to keep in their control.

P2P already has a very lively and open community that “BigCo” is trying to squash. The campaign is on to try and convince lawmakers and the public that P2P technology is Ÿber-evil nastiness that will destroy the world.

If you want to ensure that P2P technologies remain open and available, the best way to do that is to ensure that it is as easy as possible for relatively novice developers to toss together their own custom P2P solutions at whim.

Some random pile of obfuscated code makes a cute point, but it does not provide a building block for developers to perpetuate new protocols and solutions.

I would rather see the obviously talented developers of that particular script turn out a 1 pager bit of Python code that reads like pseudo-code for creating a simple P2P solution. Make the point that it is incredibly bloody easy to build a P2P solutions at whim using existing technologies and protocols.

From that, there will hopefully be lots of developers, admins and, even, users that put together their own custom little P2P solution for their own purposes. For example, given a clearly written version of TinyP2P, I would turn around a custom little script that I could drop on various family computers to sync photos around of the various kids in the family.

That kind of activity will very effectively demonstrate that P2P is here to stay. The more solutions available– the more developers whip off custom P2P solutions for their own personal needs– the harder it is to claim that P2P is a universally evil technology that must be squashed.

Stupid Dock Trick

Saturday, December 18th, 2004

Another obvious trick that I just didn’t know about. If you cmd-click on a Dock icon, the item it represents is selected in a Finder window.

I never needed that before and discovered it at random. Now that I know about it, I’m finding myself using it regularly.