Older blog entries for chromatic (starting at number 218)

A Strange Mix of Writer and Programmer:

Though most people know me for my programming, I also consider myself a writer. My day job combines both fields very nicely, but it doesn't leave a lot of room for non-technical writing.

The other night, I had a conversation spanning several subjects, including the deaths of my grandparents, the fear that I hadn't heard their full life stories, and my desire to make the world a better place, in part by helping non-programmers learn just enough programming to solve smaller problems. I felt guilty explaining the latter idea, as it seems self-indulgent in some ways and trivial in others.

As often happens, several divergent ideas ganged up on me and presented a different solution. I do want to make the world a better place, but maybe programming isn't the right place at the moment. Instead, I'm looking for a wider audience.

I've spent the past week putting the foundations of Write Your Life in place. The idea is to encourage people who want to improve their writing to practice writing every day for a month by providing one topic per day.

It uses an autobiographical theme for two reasons. First, it's important to write what you know. Though it's still difficult to start writing a thousand words about your home, once you cross that barrier, it can be more difficult to stop. (I blew past the word limit and didn't even start on the upper story of my house.)

Second, I believe everyone has a story to tell. I really regret not learning more from my grandparents while I had the chance, though my friend did point out that they may have told me as much as they felt comfortable sharing. There's a wealth of wisdom and experience in the previous generations that we may lose unless we encourage people to write and speak.

I hope my project will convince a few people to publish their own lives. Please feel free to pass the link to your friends.

(I'll try to add an RSS or Atom feed for the assignments today.)

On "Scripting" Languages:

The nice thing about saying "nobody has ever written a reliable, high-performance program" in a so-called scripting language is the person saying it controls the debate. If you point one out, he can claim that such and such a program isn't reliable enough or doesn't exhibit high enough performance.

Remember folks, it's not the experience, skill, dedication, talent, or luck of your developers, it's whether you choose a language that forces a dedicated compilation stage... at least if you're poisoning the well.

The Command-Line is My File Chooser:

Like brian d foy, I have a lot of little command-line tools to make my life easier. Today, I wrote two more.

One of the parts of Mac OS X I actually miss (and there are a few) is its open command that examines a named file and attempts to open it in an appropriate application. That's an easy program to write, if you aim for 80% effectiveness, but it's so convenient that when I found myself wishing for it today, I spent five minutes writing it.

#!/usr/bin/perl

use strict; use warnings;

use File::MMagic;

my $file = shift or die "Usage: $0 <filename>\n";

my %subtypes = map { $_ => 1 } 'application/x-zip', 'text/plain', 'text/html'; my %apps = ( 'application/star-office' => 'xooffice', 'application/msword' => 'abiword-2.0', 'application/mozilla' => 'moz_tab', 'image/jpeg' => 'eog', 'image/gif' => 'eog', 'text/html' => 'moz_tab', ); my %exts = ( 'application/star-office', => qr/\.sxw\Z/, 'application/mozilla', => qr/\.html?\Z/i, );

my $mm = File::MMagic->new();

while (my ($subtype, $regex) = each %exts) { $mm->addFileExts( $regex, $subtype ); }

my $type = $mm->checktype_filename( $file ); $type = $mm->checktype_byfilename( $file ) if exists $subtypes{ $type };

die "Unknown type '$type'\n" unless exists $apps{ $type };

fork and exit; exec $apps{$type}, $file, @ARGV;

It's worth factoring out the file types, applications, and subtypes into data somewhere, but when I find myself needing to maintain a bigger list, I'll do that.

You might notice a program called moz_tab. What does that do? I usually have Mozilla running with several tabs on a different virtual desktop. (Now you begin to see what I missed from a real window manager when I used Mac OS X!) I do want to open HTML files in Mozilla, but I don't want to open them in a new browser window or, worse, with a different profile. moz_tab checks to see if there's an existing window and opens a new tab or a window as appropriate.

#!/bin/sh

# create an absolute path DIR=`pwd` FILE="$DIR/$1"

# check if Mozilla is already running /usr/bin/mozilla -remote 'ping()' STATUS=$?

# launch a new tab, if so if [ "$STATUS" == 0 ]; then exec /usr/bin/mozilla -remote "openurl(file://$FILE,new-tab)" fi

# or launch a new window exec /usr/bin/mozilla "file://$FILE"

It doesn't check for an absolute path before absolutifying the path, but if I need that, I'll add another line.

Having both of these programs available has saved me almost a minute today. That doesn't seem like much, but keep in mind that I'd have spent that minute navigating developer-hostile file chooser windows. If I can avoid that by using the developer-friendly command line in a ubiquitous terminal window, my life is much more pleasant.

P5NCI:

The name isn't great, the available thunks are too few, the known types are too simple, and it has a tendency to rebuild the C files every time you call ./Build, but P5NCI version 0.01 works and you're more than welcome to try it and send me patches.

Alternately, tell me how cool P5NCI::Library actually is in practice.

Thanks to jplindstrom for pointing me at Win32::API which already handles structs; I think I can modify that code to work on other platforms. What's a little sizeof between friends?

Throw Away Your C Compiler (after building Perl):

#!/usr/bin/perl

# P5NCI.t

BEGIN { chdir 't' if -d 't'; use blib; }

use strict; use warnings;

use Test::More tests => 9;

use_ok('P5NCI') or exit;

my $double_lib = P5NCI::load_lib( '../nci_demo.so' ); my $double_double = P5NCI::load_nci_func( $double_lib, 'double_double', 'dd' ); is( $double_double->( 1.0 ), 2.0 ); is( $double_double->( 3.14 ), 6.28 );

my $double_int = P5NCI::load_nci_func( $double_lib, 'double_int', 'ii' ); is( $double_int->( 1 ), 2 ); is( $double_int->( 3 ), 6 );

my $double_float = P5NCI::load_nci_func( $double_lib, 'double_float', 'ff' ); is( $double_float->( 1.0 ), 2.0 ); ok( abs( $double_float->( 0.314 ) - 0.628) < 0.00001 );

my $multiply_ints = P5NCI::load_nci_func( $double_lib, 'multiply_ints', 'iii' ); is( $multiply_ints->( 10, 20 ), 200 ); is( $multiply_ints->( 5, 5 ), 25 );

The interface is a bit grotty, the documentation is spotty, the build system needs some help, and it only handles really simple functions right now, but it works.

When It Works, It Works:

After wondering exactly what poor Greg Lapore was doing when he asked, innocently enough, "Why am I receiving an error message when I try to write a demo file from SDL::Tutorial?", I realized that it's because Pod::ToDemo 0.10 was irredeemably broken.

I have no idea why it seemed to work for me, but a bit of diving into the scary details of what happens when at initialization time, a bit of interface redesign, and a few more tests later, and the new Pod::ToDemo scheme in 0.20 is a little uglier for the end-user, a lot simpler for the basic, default case for the coder, and, most importantly, a working release.

Of course, you'll need the latest SDL Perl snapshot for the updated tutorials, but they're there and work now. Hopefully Dave will soon pull the patches for the new release he's threatened.

Saving Unicode Characters as Screenshots:

I have a small project that requires extracting several Unicode characters from a Word document as uncompressed high-resolution screenshots. The only problem is that I don't have Word -- nor do I run any operating system that can run Word.

Has anyone solved a similar problem? Are there any COM gurus who know the magic invocations to dump a few dozen Kana characters to images? I suspect a decent hacker could do this in 15 minutes or so, much better than the 10 hours it would take -- if I had the tools -- to convert these manually.

Drop me a line at chromatic at oreilly dot com if that's you.

Make Small Things Easier:

I spend a lot of time sending and receiving versions of articles via e-mail. These tend to be small, generally on the order of 2000 words. I like to think of myself as a good editor, being able to improve the wording and organization of things. Still, several authors want to make changes, which is fine -- many phrasings are a matter of taste and some pieces of technology and code change for the better before final press time.

Then there are authors who make larger changes. It's easy to say "Can you change this sentence here and this word there?" It's a lot more difficult when the author moves paragraphs around and reformats the text.

Oddly, this problem almost disappears on larger projects, such as books. (See The Making of BSD Hacks.) My theory is that you'll go crazy trying to merge all of these little details on a project like this.

Why isn't a similar solution viable for articles? They're too small! The overhead of setting up a repository with authentication is too big to be useful for a maximum of three or four revisions of a 2000-word article.

Does the overhead have to be that great? I don't think so. The overhead of setting up a mailing list that lasts a week for a dozen people and two dozen posts used to be too high to be worthwhile, but Mail::SimpleList shows one way to avoid that.

This subject bears more thought. There may be a general principle here.

No Compiler, Please:

I was thinking a bit about Parrot NCI this afternoon. I usually describe it by talking about C's calling conventions and Parrot's calling conventions and then explaining that you can generate the thunking layer beforehand as you know C's calling conventions won't change. That is, a C function that takes two shorts and returns a long looks the same to the thunking layer no matter what library it's from. You can compile it once and let it do its magic for any library function whose conventions it understands.

Then I realized that I had never previously realized that Perl 5 also has calling conventions. Sure, they're a lot less strict than Parrot, but any function that passes three scalars and returns one does the same stuff to the stack.

I bet porting something like NCI to Perl 5 wouldn't be very hard. Certainly it'd be nice to replace the simpler bits of XS with something that doesn't require end users to have a compiler. Complexity does increase rapidly, but there's enough regularity that you can go quite a ways.

Just Do Something:

I've been experimenting lately with task lists, both at work and away. Since I have dozens of little things to keep track of in the next three months (roll on October!), only luck would have kept me on top of things.

Of course, being prone to yak shaving, I wrote a program to keep track of these tasks. Go on and laugh, I'll wait. Ready? It works phenomenally well.

I've mentioned how much I like Maypole. I've also always admired the way Ingy makes the installation and configuration experience easy, as exemplified by Kwiki. I've tried to do the same thing with the new installer for Everything, though that's a work in progress.

Anyhow, since I run Maypole through Jellybean to power my task manager, I've been doing a bit of work on Jellybean lately. In the spirit of my new goal to Just Do SOMETHING, I wrote Jellybean::App to simplify configuring and running a Jellybean application. It still requires you to know a little bit about how Jellybean works, but once you understand that there are servers that listen for incoming requests and named containers that respond to requests, you should find this much easier than writing a little driver script.

For example, the Jellybean::App-enabled launcher for my task manager has around four lines of code and around ten or so lines of configuration data. That beats some twenty-plus lines of code. It also gives much better diagnostics when you do things incorrectly; that by itself is a major improvement.

Sure, it's syntactic sugar, but it's quite a bit easier to explain and it took me under two hours.

209 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!