The problem with a custom laptop environment: designing it
For reasons beyond the scope of this entry I was recently irritated into putting my custom laptop environment plans into action (I do a surprising number of things due to irritation). In the interests of avoiding analysis paralysis I'm basing the first attempt on my existing fvwm-based desktop configuration (with an ever increasing number of changes). Somewhat to my surprise, the difficult part so far has not turned out to be what I expected.
My two biggest problems are related. The first one is simply designing things, in the sense of what goes where and how things will actually work (and also how I will avoid everything looking hideously ugly, which is so far being harder than I'd like). My usual desktop layout doesn't really work on a 1024 by 768 screen (there just aren't enough pixels) and I'm pretty sure I'm going to need a collection of new launchers and widgets.
(I'm basing this partly on my experience with my current Gnome 2 environment on Fedora 14, where the Gnome taskbar has launchers for several things and I use them frequently.)
The second problem is that there seem to be a huge collection of choices for the various pieces of such an environment (and some of them even work). Since I need some stuff beyond what I already have in my existing desktop fvwm configuration I've been forced into picking my way through this field of options. Many of the programs seem very powerful but their documentation is mostly focused on people who already know what they do and what they're good for; sadly this doesn't describe me right now.
(What I dream of finding is a guide to assembling your own custom desktop, laying out the options for application launcher bars, system trays, status monitors, essential applets, and so on. Given the huge amount of work it would take to assemble such a thing, this is crazy talk.)
On a closely related issue, I will note that there is nothing like
trying to copy bits and pieces of your personal environment to another
machine to rub one's nose in just how intertwined, baroque, and
encrusted with various relics of history the whole mess is. I'm getting
very tempted to conduct a slash and burn expedition through
in order to clean up a bunch of things.
(I should not have just looked at how many files I have in there, because the answer is 'too many'.)
PS: part of my uncertainty is that I haven't tried my in progress environment on the actual laptop yet. So far I've only been working in a VM (at the right resolution) since I wanted to have the basics there before I reinstalled the laptop.
Update: all my grand plans fell through spectacularly when I tried my in-progress environment on the actual laptop. See here for the depressing update and reversal of plans.
Sidebar: on the matter of alternate window managers
Most of the popular modern window managers for minimal desktops seem to be primarily or entirely tiling ones. From current experience with my laptop, a 1024 by 768 resolution is simply too small to not have plenty of overlapping windows (and thus a whole bunch of support for moving, restacking, and resizing windows). I also like using some amount of the mouse and don't want to have to memorize a big list of keyboard sequences for a machine that I only use infrequently.
I've looked briefly at awesome but the idea of writing Lua to configure my window manager is even more extreme that fvwm's elaborate configuration language. Maybe I'll try it some time for a (strictly hypothetical) version two of my custom laptop environment.
A Python code structure problem: exception handling with flags
Here's a Python (2.x) code structure puzzle that I don't have a good answer for yet, except that maybe the answer is that my overall design is a bad fit for what I'm doing. To start with, suppose that you have a multi-level, multi-step process of processing lines from an input file. Any number of things can go wrong during the processing; when it does, you need to bubble this information up to the top level but keep on going to process the next line (if only so you can report all of the errors in the file in one pass). The obvious fit for this is to have errors communicated by raising exceptions which are then trapped at the top level.
Now let's suppose there are several different sorts of errors and you want to treat some of them specially based on command line flags. For example normally all errors are fatal and show error messages, but some can be suppressed entirely with a flag (they just cause the record to be silently skipped) and some can be made into warnings. How do you structure this in the code?
My first version looked something like this:
try: data = crunch(line) .... except A, e: report(e) commit = False except B, e: report(e) if not option.skipempty: commit = False except C, e: if not option.skipdups: report(e) commit = False
All of the duplication here made me unhappy because it obscured the
actual logic and makes it easy for one exception to drift out of sync
with the handling for the others.
I can aggregate everything together with '
except (A, B, C), e:' but
then the question is how to write the single exception handler so that
it's both clean and does everything necessary; so far I've thought of
two approaches. The first approach is to use
tell what sort of exception we have and then write out the conditions in
if's, except that trying to do that makes for ugly long conditions.
(I started to write out the example above and basically exploded in
irritation when I got to the
commit logic, which I decided was a bad
sign. It also looked like the result would be very hard to read, which
means that errors would be easy to add.)
The second solution I've come up with is to add attributes to each
exception class, call them
nocommit. Then at the start of
the code we do:
if options.skipempty: B.nocommit = False if options.skipdups: C.report = False C.nocommit = False
In the main code we do:
try: .... except (A, B, C), e: if e.report: report(e) if e.nocommit: commit = False
This avoids both duplication and lack of clarity at the expense of, well, kind of being a hack.
(You can also code a variant of this where
functions that are passed the
options object; this puts all of the
'what turns this off' logic into the exceptions themselves instead of
reaching into the exception classes to (re)set attributes. That might be
somewhat cleaner although it's more verbose.)
Given that all of the options have drawbacks I feel that there ought to be a clever Python code design trick that I'm missing here.