So again, a lick and a promise for this blog as I madly try to finish some translation work. This translation job is an interesting one, though, as I mentioned, and as it turns out, amenable to editing in a specialized tool I just wrote today. Of course, having written the tool today means I have to use the tool this evening in a mad dash to finish, which in turn means I have no time to document the code until tomorrow at the very earliest.
Suffice it to say that the exercise was surprisingly easy. The task was simple: I need a tool to edit text files in which (for reasons we'll go into later) I have a number of phrases, one per line. The phrases mostly have all the right words in them, but not in the right order. I thus need a way to quickly select one or more words and drag it into the right place in the phrase. Sure, you say, Word does that. Yeah, except that Word doesn't put the spaces in the right place. God and Bill Gates alone know why, but Word doesn't put the fricking spaces in the right place when I drag words around on a line, and so I took matters into my own hands and rolled my own solution. And by God it works! Still a few little oddities in it, but it works more quickly than Word for this particular application.
Another nice thing it can do is this: when I drag the first word of a phrase out into the middle, it can decapitalize that word, and capitalize the new first word. That saves me a fraction of a second, and multiplied by 2000 phrases that adds up to a lot of time.
And another little thing I just now added: I can hit a key and toggle the case of the word the cursor is on. Again: this may or may not be of general use, but for this particular application it's very convenient. And that's really the idea of special-purpose text editors. An example from the programming world is emacs -- you can write LISP code to make emacs do literally anything at all (including psychoanalysis) from your text editor. The only problem being that it's too damn hard to start. Python's easier, at least for me. So a text editor in which you can embed your own Python snippets might be a generally useful tool indeed!
So. Tomorrow or Sunday, documentation and maybe some more movement on the drop tagger. And in the meantime, go get some sleep! (I know I won't any time soon.)
So my first actual weekly application is finished now. Aren't you proud? Suffice it to say that even a minor app takes a few hours to put together when you're reworking all your programming tools at the same time. A character flaw, I suppose. I never use an already-invented wheel if I have a perfectly good knife and wheel material. And I never use an already-invented knife if I have a perfectly good grinder and stock metal. And I never use an already-invented grinder if I have a lathe, motors, and a grindstone. And I never use an already-invented lathe... (sigh).
At any rate, it took me a few hours more than I wanted, but I'm reasonably pleased with the result. You can see the whole thing here (it's far too long to publish on the blog directly, of course). Go on. Look!
For some time, in the context of my workflow toolkit, I've been thinking intensively about UI design in wxPython.
See, once I was embroiled in a rather extensive project developing a GUI application under wxPython, and frankly, the UI was unmanageable. It had been developed with some IDE tool or another, but the output was Python code. It was horrible, trying to find what was what and on which panel it was developed and what its ID was -- ugh! This was back in about 2001.
At that point, I hadn't really started integrating wftk into Python yet, but I dabbled in it over the next couple of years, always with the notion that the UI is most sensibly defined in XML, and that a sensible UI manager would then take that definition and build all the objects needed to implement it in wxPython (or, for instance, online in a portal or something). And since that time, other people have naturally had many of the same ideas, and you see this implemented. But I've always wanted to finish my own implementation.
The current app for Anappaweek.com that I'm working on is, of course, a GUI app (at least, some of the time.) And so naturally I have relived my need for my UI design notion -- and in the context of working on the file tagger, I intend to start implementing the UI module. On that note, here is a tentative UI definition sketch for the file tagger. Ideally, we could use this XML not only to generate the app itself, but also to generate documentation for the UI design (by transforming it with XSLT into SVG, for instance; wouldn't that be indescribably cool?)
All of this is, of course, subject to radical change. Here goes:
<frame>
<tabset>
<tab label="Cloud">
<html>
</tab>
<tab label="Files">
<splitter (some kind of parameters)>
<panel>
<radio-group>
<radio value="something" label="All"/>
<radio value="something" label="Some"/>
</radio-group>
<listbox/>
<button label="Show"/>
</panel>
<listcontrol>
<col label="Name"/>
<col label="Tags"/>
<col label="Description"/>
</listcontrol>
</tab>
</tabset>
</frame>
I already have a framework for that definition to go into -- I wrote that in, like, 2002 or so. But I never got further than definition of menus. So here, I'm going to implement frames, and at least one dialog.
Note that what's utterly missing from this is any reference to code to handle events. That will come later, when I see what has to be defined where to get all this to work.
And on that note, I close.
At long last, I managed to finish development on a first cut of the filetagger application. It took far longer than I really wanted it to, because I spent an inordinate amount of time whipping the wxpywf framework into shape (about a month) and so the whole "app a week" thing is more like "an app per five weeks" or so. Ha.
But you know what? I did it! I actually brought a major new module of the wftk, one I'd been thinking about for three years, to the point where it can be used. Wow.
So I'm glad I took the time to do it the way I wanted to do it.
Here are some of the features of wxpywf I created and used for this app:
- XML definition of the entire UI of an application, using frames and dialogs. In comparison with the traditional call-by-call technique for setting up a wxPython UI, this is incredibly convenient.
- Application-specific code grouped into simple commands.
- Each frame and each dialog automatically binds to an XML record which can be addressed on a field-by-field basis.
- HTML can be used for more textual interfaces; links generate commands which can have arbitrary effects on the UI (in this case, clicking on a link in the tag cloud switches the tabbed frame to the file list and displays the files with the tag selected.)
- So far, the UI can include tabsets, list controls, HTML windows, rich text controls, checkboxes, radio button groups and listboxes, command buttons, and static text.
There's a lot of ground still to cover. But in my experience, that kind of ground can be covered in small, manageable steps after initial usability is there. And initial usability is definitely there. I feel really happy about this.
I posted the second appaweek project last week, based on the wxpywf framework from the wftk, as you know. And this week I've started mulling over app #3, and since I'd upgraded from Python 2.1 to 2.4, my old (ancient) copy of the McMillan installer was way outdated. Turns out that McMillan disappeared from the Net in about 2004, but some enterprising souls (headed by a guy in Puerto Rico, no less, at UPR!) have taken up the gauntlet and are continuing development under the name PyInstaller.
So that was good, but when I got down to business compiling the little filemonitor work-in-progress, I found that the wx libraries have now grown in size, with the result that the (already somewhat heavy) 2MB size of a simple compiled wx app has now become 5MB! Wow! (Of course, that includes the runtime and everything, but still...)
I don't want that kind of stuff bogging down my server, and already there has been respectable traffic around the appaweek projects. But there is an awful lot of specialized code involved in this venture: wx itself, of course, and the wftk's xmlapi and repmgr libraries, their Python wrappers, and the wftk and wxpywf OO wrappers around those. That's a lot of stuff to make people install, especially on Windows when they may simply have to install Python to start with! Which is why I wanted to do the compilation thing in the first place, of course.
So here's what I thought to do -- and this is what wxpywf was always intended to do: I brought the PyPop app up to date so that it displays the XML-defined UI just fine. And it would then be possible to do dynamic importation of a module to complete the application; PyPop already contains Python and all the libraries necessary to run things, so that would work fine. And yes, the UI for the filetagger app (app #2) displayed fine, although it naturally didn't do anything except display.
But then it occurred to me: Wouldn't it be nice if wxpywf could look at the XML definition of the UI and go ahead and build the CLI definition? And then I realized that if PyPop could (1) interpret the command line and put the results into the context, (2) load the data file and do the necessary Python indexing of it, and (3) build a Python CLI on the fly and link it to the frame, then, then...
Then the entire app would be in one XML file!
And a little bitty one, too, a whole app in about 20KB. That's a quick download! And then:
If the download of the app were managed through PyPop then we'd really have a Swiss Army Knife for software! And of course, more serious Python requirements could always import a Python file for better clarity, leaving the main application to define the CLI glue holding it all together.
Then envision this: imagine an application repository, and imagine the PyPop tool as a custom-thick-client "browser" of sorts. The local PyPop installation would manage common dialogs and applications in a versioned repository, and could check for updates every time you ran an app (or on a schedule). You could design your own UIs and submit them as project requests, and have a programmer fill in the hard parts. Every app built on this framework already knows about data management from the repmgr and about workflow from the wftk, it has logging and macro capabilities built in, and it runs Python. It could run Perl if you wanted to install it -- Perl's easy to embed in Python.
You'd know where all your little apps were, and you could trade them through the central repository or you could set them up for download yourself.
That would be pretty neat. Pretty neat indeed!
Wow. This wasn't something I'd budgeted time for, but it works. I have reimplemented the filetagger app as a single-file definition, including action tags using a very convenient abbreviated notation for wxpywf-relevant Python. For instance, the code to execute a command against the frame is
self.frame.do(context, 'update_list')
in undecorated Python. In the action, it can be just
: update_list
The wxpywf then scans the entire UI definition for action tags; for each, it builds the Python code, wraps the whole thing up as a Python class inheriting from wftk.cli, and returns it to the caller, which can then exec it to define the class.
The error handling leaves much to be desired; in case of a syntax error, it's almost understandable where the error is, but in case of a runtime error, Python's stack trace is essentially useless (file <string> line 90 doesn't help much with invisibly generated code.)
But it is cool, and on-the-fly code generation is always something I wanted to find a legitimate use for. And now I have!
At any rate, I obviously need to get a lot of code uploaded at some point and documentation caught up, but now is not the time. Work beckons, frantically.