Subscribe: One for the Morning Glory
Added By: Feedage Forager Feedage Grade B rated
Language: English
apt  aptitude  call  cmdline cmdline  cmdline  debian  don  function  generic apt  generic  mail  microsoft  monad  new  reader  time 
Rate this Feed
Rate this feedRate this feedRate this feedRate this feedRate this feed
Rate this feed 1 starRate this feed 2 starRate this feed 3 starRate this feed 4 starRate this feed 5 star

Comments (0)

Feed Details and Statistics Feed Statistics
Preview: One for the Morning Glory

One for the Morning Glory

Updated: 2017-12-14T17:38:39.264-08:00


My blog has moved.


My blog is now hosted over here:

Facebook comments


My blog is syndicated on Planet Debian, Planet GSLUG, and Facebook (through their "notes" system). I occasionally get a comment about one of my posts over on Facebook, and every time I do I remember one of the reasons I avoid that site.

[someone] made a comment about your note "note title".

To see the comment, follow the link below:
[link to Facebook]

What's missing here is of course the actual text of the comment. Blogger does this right: the actual comment is emailed to me. Not only does this impose the annoyance of having to click on the link, but I often read my email offline, and so a message like this is worse than useless for me. (worse as I have to postpone it for later, which means I need to deal with it twice) It would be even better if I didn't have to click to reply, but with a Web service you kind of expect that. (one of the reasons that I'll be setting up my own blog at some point: I can use software that actually allows me to compose replies offline)

I don't know why Facebook does this, but my guess is that either (a) they haven't thought about it, or (b) they want to drive up page views and make it annoying for me to not use their site. If it's (b), then that apparently works for a large swathe of the population, but it makes me want to avoid them like a bad cliche.

[EDIT] This post is attracting spam; closing comments.

Good ideas in customer service: kill the hold period


The lender for one of my student loans has apparently started using a rather cool system to manage incoming customer service calls. If all the call-takers are busy, then instead of forcing you to sit there listening to a call telling you how important your business is to them, they let you request a call-back. They ask you to enter a phone number where they can reach you, then give you a time window in which they'll be calling (in my case I think it was about two minutes wide). When my turn came up, they called me and I was able to speak with a human immediately.

This is such a huge improvement over the typical call center experience that I'm amazed it hasn't caught on more broadly.

  • It's presumably good for them since they don't have to pay for a long incoming toll-free call, particularly when most of the call is just muzak.
  • It's great for me, because instead of sitting by the phone like a hawk in case I miss the customer service rep, I can go do something useful for a few minutes until the time the call is scheduled for.

I'm guessing that this option will be available in more and more places as companies computerize their telephone systems. Another nice twist, if there are any telephony guys reading this, would be to allow me to request the customer service call from a Web page, eliminating the toll-free call altogether and presumably saving some expense for the company.

An interesting question for me is how they generate those estimates of when they'll be able to help you. I'm guessing that they use some queueing theory to estimate the most likely wait time for the next incoming customer, but this is something I have only a fuzzy awareness of. However they did it, the estimate seemed accurate enough to me.

cwidget gets a Web page


I spent some time last weekend putting together the infrastructure to generate a basic Web page for cwidget. The Web page is generated by Ikiwiki (thanks to the incomparable Joey Hess for a really nice piece of code there) and doubles as the cwidget documentation; it will be included in the next upload of libcwidget-doc. It can be found in the source tree under doc/ikiwiki.

It's currently a bit skeletal: in particular, it really needs some tutorial/HOWTO material for new users. But it at least has all the basic information that I personally expect from a project Web site.

I was playing with ikiwiki for a week or so prior to setting this Web site up, and the more I use it the more impressed I am. When I get my new Slicehost instance set up (probably next weekend), this blog will probably migrate to an ikiwiki installation over there. Being able to edit my posts offline (about half my hacking time is offline), being able to expose a change history for posts, and not having to maintain an installation of a monster PHP program (as the docs put it, if you don't run the CGI then ikiwiki has the security implications of cat(1)), are all absolutely killer features for me, and I look forward to expanding my use of this tool. Joey has struck gold yet again.

[UPDATE] This post is attracting spam and no real comments. Closing comments.

ANNOUNCE: cwidget


I've just uploaded the first release of libcwidget to Alioth and NEW. libcwidget is a high-level C++ library for developing user interfaces that run in a terminal using curses as the display and input layer. It uses widget abstractions similar (but of course not identical) to those found in GTK+ and Qt, with signals and slots provided by libsigc++.


Back when I started writing aptitude, I had one general goal:

Just because it runs in a terminal doesn't mean it has to suck.

I tried to apply this in the user interface, but I also applied it internally. The curses programs I looked at before writing aptitude all had very ad-hoc UIs. In many cases the code was structured with each "view" that appeared mapped to a custom C function call; if the author was feeling ambitious, similar-looking screens might be abstracted into a single function call, but the basic structure of the interface still reflected the call graph of the program.

aptitude had a primitive interface abstraction layer from the get-go; over the years, I borrowed ideas from GTK+ and restructured this layer into a full widget set. libcwidget is this code, disentangled from the guts of aptitude and slightly cleaned up. Because of its history, it is missing widgets that aptitude doesn't need (like a multi-line text editor), but it provides an extensible base that you can build upon.

Getting cwidget

The cwidget library is available (both as source and as an i386 .deb) from the cwidget Alioth releases page. There is also API documentation automatically generated from the upstream repository, which, while it is woefully incomplete, should provide some information: I've tried to write Doxygen tags into most of the code I've added in the last 4 years or so.

The upstream code repository is in git (because what fun is a new project if you don't learn a new VCS?) and available here. To retrieve a copy of the repository for yourself, run this command:

git clone git:// cwidget

Building rails


In the 1860s, in the middle of one of the largest wars America has ever been involved in, a 690-mile railroad was built in a period of seven to nine years (depending on how you count), a rate of about five days per mile of track. Now, it's certainly true that this was accomplished through labor practices that were, by today's standards, more than a little bit questionable. However, I still am amazed that it's apparently going to take us twenty years to construct fifty miles of track in the Seattle area. By my count, that's a hundred and forty six days per mile of track. And I haven't even mentioned the harsh environmental conditions the transcontinental line faced, which a line in the Seattle metro area by and large does not.

I haven't decided how or whether to vote in the election tomorrow, but the timescale they're projecting is ... astonishing.

Lessig at the University of Washington


On Friday 2007-11-02, I watched Larry Lessig give a presentation at the University of Washington entitled Is Google (2008) Microsoft (1998)? Since it was Lessig, the talk was articulate and thought-provoking, and he used his slides very well (unlike many presenters who just read bullet points).The argument he made is that Google is like Microsoft in some ways (and so are other companies like Facebook). In his analysis, the problem with Microsoft was that so many companies made themselves Microsoft-dependent, which both forced other companies to follow suit (due to network effects) and gave Microsoft leverage they could use against everyone in their ecosystem (e.g., Netscape). According to Lessig, Microsoft was not evil to use this leverage, but you have to recognize that Microsoft will do what is best for Microsoft, and this may not be what is best for you. He then suggested that we should be aware of the potential for the same thing to happen; in support of this point, he quoted excerpts from the terms of service from the APIs of Google and Facebook, which contain typical statements like we reserve the right to terminate your use of this service for any reason or for no reason, and asked: What if Microsoft had written this license agreement?But it seemed to me that this wasn't his main point. He was using this observation as a springboard to talk about issues revolving around competition and public policy. Specifically, he feels that we should work towards a more just model of interaction between companies and users whose work makes the company more valuable (by contributing to a software ecosystem, by posting content on the Web site, etc). But the correct way to do this (he says) is not via competition, after-the-fact litigation, or voluntary codes of conduct: competition may not be around to enforce good behavior (as we've seen with Microsoft), litigation may be too late and ineffective (again, see Microsoft), and voluntary codes of conduct will disappear as soon as they get in the way of the bottom line. The correct approach, he argued, is across-the-board regulation so that all the companies have to play by the same rules.From there he went on to talk about governmental corruption. He said (quoting Robert Reich's book Supercapitalism) that the reason we consistently look for solutions in the market and in voluntary compliance is that our governmental system is broken and does not effectively regulate corporations in the public interest. But Lessig is optimistic that we can change things (he joked that his publisher was unhappy with this point of view, because his brand has been built on pessimism). In his view, the politicians in Washington, by and large, want to be honest and do good, but they aren't able to within the current political system. For instance, on the few occassions that he managed to get access to lawmakers to discuss copyright issues, it was often the first time they had heard that there was more than one side to the argument. He thinks we need a national political movement that will shame politicians into being less corrupt.This is all a simplification of what he said, of course; unfortunately, I wasn't able to find a recording of this talk on Lessig's Web site, or I'd point you at primary source material. I don't know if this is because he chose not to post it, or because it just hasn't been made available yet.My viewIn general, I thought that the speech was very interesting and well thought out. But as much as I'd like to buy into his optimism that we can fix our system, I don't think it's well-founded, for two reasons.First, he argued that competition will resolve some of these problems (that was before and after he said we can't rely on competition, which I found confusing and may indicate that I misunderstood something). His evidence for this seemed to be that when Microsoft was dominating the world, users responded [...]



Amusing tidbits you pick up in the mailing industry...

No, you can't mail running chainsaws. At least I'm pretty sure about that; I don't know a specific regulation against them, but USPS takes a dim view of anything that puts its employees and machinery at risk.

On the other hand, you can mail live scorpions if you package them appropriately. Note that, however, that this is limited to the US; apparently doing so in Australia is not a good idea. The same page also gives the rules for mailing baby chicks (which must be not more than 24 hours old) as well as adult chickens (Express Mail only, please; and no refund if the chicken dies in transit unless the container was damaged).

Here we go again...


[10/30/2007]Version 0.4.7 "Where did all these balloons come from? And why am I wearing a fake nose?"- New features: * The options dialogs have been completely replaced by a new interface, based on a top-level list view. This fixes many deficiencies of the old interface: it handles long strings more gracefully, avoids many of the focus-handling bugs that the old dialogs had, and should generally be better-behaved. (Closes: #197976, #331200, #424708) * Prompts that ask you to enter text will now wrap to multiple lines when the text gets long, rather than hiding parts of the string. * The online help and other Help-menu itmes are now top-level views, which should make them somewhat more usable. (Closes: #434349) * Support for the "Breaks" field and for trigger states (thanks to Michael Vogt and Ian Jackson for patches and prodding). (Closes: #438543) * Two new styles, "PkgDowngraded" and "PkgDowngradedHighlighted", are provided to control how downgraded packages look. By default these packages look like any other installed package. (Closes: #434442) * aptitude can now display homepage URLs stored in the Homepage field of packages.There are bug-fixes too, but those aren't as fun. So instead I think I'll include some diffstat output. Everyone likes diffstat!daniel@alpaca:~/programming/aptitude/head$ hg diff -r | diffstat .hgtags | 1 NEWS | 92 + b/src/ | 477 ++++++ b/src/apt_config_treeitems.h | 156 ++ b/src/generic/util/browser.h | 42 | 20 doc/en/aptitude.xml | 187 ++ help-fr.txt | 10 po/ChangeLog | 24 po/dz.po | 188 +- po/es.po | 82 - po/gl.po | 19 po/ne.po | 1277 +++++++++-------- po/pt.po | 20 po/ru.po | 97 - po/sv.po | 1854 ++++++++++++-------------- po/zh_CN.po | 23 src/ | 2 src/ | 4 src/ | 598 +++++--- src/apt_options.h | 12 src/cmdline/ | 6 src/cmdline/ | 2 src/cmdline/ | 134 + src/cmdline/ | 124 - src/cmdline/ | 4 src/cmdline/ | 20 src/cmdline/ | 64 src/ | 4 src/ | 1 src/ | 2 src/generic/apt/ | 32 src/generic/apt/apt.h | 30 src/generic/apt/ | 54 src/generic/apt/aptcache.h | 21 src/generic/apt/ | 28 src/generic/apt/aptitude_resolver_universe.h | 57 src/generic/apt/ | 22 src/generic/apt/ | 8 src/generic/apt/ | 531 +++++-- src/generic/apt/matchers.h | 28 src/[...]

Just rub it in, why don't you!


One of my co-workers told us about a message he saw posted on a British message board about Royal Mail. For people whose job does not involve postal systems, Royal Mail is the semi-governmental semi-monopoly that handles mail in the UK; it's a little like the USPS in the States.

The funny thing about the message had little to do with the mail: apparently the poster was saying that Royal Mail's standards have deteriorated because he can no longer pick up his mail at 9:30 AM, before he goes to work. Dude! You don't even have to leave for work until 9:30 and you're complaining about when your mail comes?

I bet he gets four weeks of paid vacation, too, and then complains about how that isn't enough.

Mercurial repositories for the aptitude Debian tree now publically accessible


Since I switched the aptitude repositories over to Mercurial, I've been using hg-buildpackage to produce Debian packages. I wasn't sure at first if it would work out, so I didn't publish the repositories, and then I got swamped with work. But I've had good luck so far with hg-buildpackage, so I've uploaded the Mercurial trees to Alioth. You can find the upstream branch here:

and the Debian branch here:



The Reader monad is a simple and easy-to-use structure from the Haskell library that solves a common problem.Very often, it's the case that you have a lot of functions that all need to use the same values. For instance, you might be laying out some text on a page, and you need to keep the details of the page size around in all your layout algorithms. Typically, you handle this situation by adding a new parameter to all your functions which represents the state. So,layoutPage :: Text -> PagebecomeslayoutPage :: PageLayoutParams -> Text -> PageThis works just fine, but it can get really ugly. Every single function gets a new parameter, which must be threaded through to every related function that it ever calls. This causes visual clutter, particularly for functions that don't actually use the parameter themselves but just pass it on.A function written in the Reader monad is augmented with a hidden parameter. For the hypothetical example above, we would write:import Control.Monad.Readertype LayoutFunc = Reader PageLayoutParamslayoutPage :: Text -> LayoutFunc PageNote that the Reader monad is partially applied here. The result, LayoutFunc, is a new monad that adds a parameter of type PageLayoutParams to any code that runs inside it.So, now that we have this monad, how do we use it? The "ask" operation retrieves the parameter that's hidden in the monad:ask :: Reader a aor, specialized to LayoutFunc:ask :: LayoutFunc PageLayoutParamsIn order to remain close to the example in question, I will provide specialized type signatures for the rest of the library functions. You can find the generic type signatures in the Haskell library documentation for Control.Monad.Reader.Suppose that layoutPage started out like this before it was moved into the monad:layoutPage st txt = let width = pageWidth st ...In the Reader monad, this becomes:layoutPage txt = do st PageLayoutParams) -> LayoutFunc a -> LayoutFunc alocal executes an operation in a context modified by its first parameter. For instance,layoutSubPage newWidth txt = local (\st -> st { pageWidth = newWidth }) txtFinally, to actually invoke a computation in the Reader monad, use runReader:runReader :: LayoutFunc a -> PageLayoutParams -> amain = showPage (runReader defaultPageParams someText)For much more information on the Reader monad, see All About Monads, or the Haskell library documentation.[...]

Science: who does it, why?


On the topic of "why so few scientists are women", I recently came across a rather thought-provoking article (thanks Erinn). It's worth a read, especially for anyone (man or woman) that's thinking about heading into academia.

Feline Love


Coding while a cat kneads your chest: awkward.

Coding while a cat sleeps on your face: difficult.

Coding while a cat nibbles on your fingers: painful.

Coding with a cat snuggled up against your side: adorable.

What were they thinking?


If you're going to build a computer case that looks like a media player ...

and if you're going to include a big volume control and an LCD player on the front ...

then aren't some buttons like "play", "next", and "pause" also a good idea?

I ask because I was browsing computer cases at the store yesterday, and apparently no-one working for the companies that design these things has thought of including some control buttons on front. To me, this seems like it would rank somewhere in the top 10 most obvious ideas ever, somewhere below "eat when you get hungry" and above "don't pick a fight with a grizzly bear", but clearly I'm missing something.

Seattle LUG meeting


The Seattle Linux user's group has been defunct for the last two years or so, but an effort is underway to renergize it. This Saturday, the group will be meeting for the first time in years. The meeting will take place at the North Seattle Community College beginning at high noon -- check the official Web page for more details. TBH, the presentations don't look that interesting to me, but it's always fascinating to meet people who actually use Linux...

Yes, I'll be there, but I'm not giving any of the presentations, so please don't let that keep you away. ;-)

Do not install aptitude 0.4.4-4b+1!


Apparently someone decided to resolve the dependency problems with aptitude in unstable by doing a blind recompile and NMU of the package, presumably because of my horrible laziness in not doing an upload to unstable yet. The problem, as I wrote in the bug reports regarding the need for a recompile, is that this produces a package that's totally unusable, which is why I didn't do it myself. If you are running unstable, you should either not upgrade the apt system, or install the experimental aptitude (either using "apt-get install aptitude/experimental" or by going here). These packages are not perfectly stable, but they also aren't totally unusable.

I apologize for the inconvenience -- if I can get some time this evening I'll rebuild the aptitude in experimental and throw it kicking and screaming into unstable.



I've been suffering for a while from mild jealousy of the people who have a spare week of vacation time to make it to Edinburgh for DebConf. (is there a support group for this? :) ) But now I read that some people apparently have so much time off that they travelled to Edinburgh a full week ahead of time, just because, y'know, they could. Darn Europeans.

But then, I only have to work for another year and a half before I qualify for another whole week of vacation time, raising the total to three weeks off per year. Maybe I can make DebConf 2009, assuming that President Hillary doesn't invade Luxembourg or something...

Fun with Functions


Pete Nuttall writes about the fnreduce function:fnreduce :: [(a->a)]->a->afnreduce [] value = valuefnreduce (a:as) value = freduce as $ a valueA shorter, although not necessarily clearer, expression of this function would befnreduce as value = (foldr (flip (.)) id as) valueThis just says that to apply a list of functions to a value, we first compose all the functions by folding down the list, then apply the result to the value. The important thing here is (flip (.)), which says to compose backwards; it means that fnreduce [f, g, h] returns (h . g . f . id) instead of (f . g . h . id). An interesting side note is that it doesn't matter (from a semantic point of view) whether I use foldl or foldr, since function composition is associative:f . (g . (h . id)) = ((id . f) . g) . hBut "flip" here feels a little confusing. A clearer approach would be to reverse the list instead of reversing the operator:fnreduce as value = foldr (.) id (reverse as) valueThis might be less efficient, but it says in a much clearer way what I'm doing.Yet another option is to eschew the use of function composition:fnreduce as value = foldl (flip ($)) value asHere ($) is the application function; (f$x) applies f to x. So if we reverse it (call this $$), we get (x$$f) applies f to x. Folding this from the left down the list [f, g, h] gives us (((value$$f)$$g)$$h), which is exactly what the original fnreduce did.I think this is maybe the best fold-based solution to the original problem, because it models what's happening (repeatedly transforming a value with a series of functions) directly. To use a right-fold, you have to remove the flip and reverse as (the reason this is necessary is left as an exercise to the reader).Pete also asks whether this can be done for heterogenous lists in a type-safe manner. The core problem is, what is the type of our list? It can't actually be a list: in order to check that it's OK to combine the output of one function with the input of another, we would need the elements of the list to have different types. You can't do this in Haskell, even a crazy ghc-extended Haskell.So, we could try something like this:module Test wheredata TransformList a b where Nil :: TransformList a a Cons :: (a -> b) -> TransformList b c -> TransformList a capply :: TransformList a b -> a -> bapply Nil = idapply (Cons f fs) = (apply fs) . fThis lets us do stuff like> apply (Cons (\x -> x + 1) (Cons (\x -> show x) Nil)) 5"6"This is cute, but I don't know that it's really that useful. After all, how is it any better than the following?> ((\x -> show x) . (\x -> x + 1)) 5"6"Everything the above code lets you do with TransformList could just as well be done with the humble compose operator. The only benefit would be if we could somehow do "list-like" stuff with a transform list. For instance, say we want to write the following function:traceIntermediates Nil x = (x, [])traceIntermediates (Cons f l) x = let x' = f x (x'', ss) = traceIntermediates l x' in (x'', (show x'):ss)This won't compile, because we don't know that x' is a member of the Show typeclass. And there is no way to fix this in a reusable way using any technique that relies on building a type parameterized on the input and output types: the problem is that we need to say something about the types of the intermediate values, but their type variables are inaccessible.In other words, there isn't any way to write down a constraint on the type "TransformLi[...]

Freudian slips in commit messages


changeset: 700:d8308a89c519

user: Daniel Burrows

date: Sun Jun 17 16:22:43 2007 -0700

summary: Call pre_package_state_changed() before undoing, to resent the dependency resolver; call package_state_changed() after an undo if necessary.

aptitude development moves to Mercurial, back to Alioth


Short version: the aptitude development tree is now maintained using Mercurial, go here to fetch it.

aptitude development has been using darcs as a version control system for the last two years. Darcs is a distributed version control system with many great concepts -- but it has one huge, glaring, enormous flaw, which is that innocuous operations, like merging one branch into another, can require practically unbounded amounts of time and space. And once two branches get screwed up in this way, there is nothing, nothing at all, that you can do to get yourself unwedged; the cause is a design flaw in darcs that no-one seems to know how to fix or work around.

Recently, I made the mistake of changing some files in both the Debian branch of aptitude and the head branch, and when I tried to merge the two branches to upload a new upstream release, darcs went off into la-la land. So, I figured that it was probably time to switch version control systems.

I'd like to say that I did extensive research on the matter, but the truth is that I chose Mercurial based on the fact that (A) a lot of ex-darcs users have written nice things about it, (B) git and arch-derived systems always feel ugly to me, and (C) John Goerzen implemented support for mercurial on Alioth. Yes, I am so a follower.

So if you want the up-to-date aptitude source, you should go to You can also fetch an RSS feed from

You can fetch a copy of the repository with "hg clone aptitude-head". To update, I recommend putting the following lines in ~/.hgrc to enable the "fetch" extension:

hgext.fetch =

Once you've done this, just run "hg fetch" and it should download and merge the latest code. You may want to install kdiff3 to get a better merge tool as well.

To commit a patch locally, run "hg commit". Unfortunately, there doesn't seem to be any easy way for people to send patches back within the VCS like there is for darcs (one of many nice features I had to give up in favor of being able to actually get work done -- what, me bitter?), but it looks like you can get somewhere with "hg bundle ", then mailing the resulting file off.

Dear Lazyweb: Mercurial Python API


So, in the midst of trying to convert some Darcs repositories to Mercurial repositories (see here for the reason), I hit an "interesting" bug: tailor processes "rename" patches by deleting the renamed file. A little debugging later, I get to this simulation of what tailor does:

>>> from mercurial import hg,ui
>>> uio = ui.ui(debug=True,verbose=True)
>>> r = hg.repository(ui=uio, path='.', create=True)
>>> f = file('A', 'w')
>>> f.write('Some data\n')
>>> f.close()
>>> r.add('A')
>>> r.commit(text='Add A')
>>> r.copy('A', 'B')
B does not exist!

Huh? Of course B doesn't exist, that's why I want to create it! So, we look at the code in to handle copying...

def copy(self, source, dest, wlock=None):
p = self.wjoin(dest)
if not os.path.exists(p):
self.ui.warn(_("%s does not exist!\n") % dest)
elif not os.path.isfile(p):
self.ui.warn(_("copy failed: %s is not a file\n") % dest)
if not wlock:
wlock = self.wlock()
if self.dirstate.state(dest) == '?':
self.dirstate.update([dest], "a")
self.dirstate.copy(source, dest)

Double huh?

  1. Why is this method checking whether the destination exists before it does anything? It appears to me that this is actually necessary; just disabling this test leads to a crash later.
  2. How does mercurial work at all with such huge breakage in its core code? Does /usr/bin/hg use a different implementation of the repository code than mercurial.hg?
  3. Why, in the name of $DEITY, is this a warning and not a fatal exception? One example of what happens when you don't signal to your users that you're ignoring them is this bug: tailor happily goes ahead and removes the original file, safe in the knowledge that mercurial has copied it to the new location. Except, of course, that mercurial hasn't actually copied it. Whoops.

I'm hoping that someone will tell me that it's just too late at night for me and I'm being an idiot. Please tell me this. It would make me very sad if code like that was in my VCS.

:-( <--- sad Daniel

Closing bugs just because they're old is not cool


Two bug reports that I wrote were recently closed with the following explanation:

Last message was posted nearly three years ago. Considering abandoned and closing.

Whoops, I thought, I must have missed a request for more information. So I went to the bug page and, nope, the only message on the bug was my initial report.

Let me repeat that: the total sequence of interactions on these bugs was:

  1. I report a bug in 2004
  2. Someone closes it in 2007 because it's "too old".

Now, there are times when it's at least somewhat excusable to close old bugs without verifying that they're fixed (or even knowing that they might not be). When a package has hundreds of bug reports, closing old bugs that can't be reproduced can be a good thing: even if the reports are valid, keeping reports that can't contribute towards a fix around is arguably less useful than cleaning out the bug list so it's usable.

In my case, though, the package in question has only 20 or so bug reports, an easily managed number. Worse, both bugs I reported could be trivially reproduced. One of them was arguably not a bug, but the guy who closed my bugs did not argue that; as far as I can tell, he didn't even look at my bug report.

Notice that I haven't mentioned the maintainer of the package? That's because he didn't close the bug. In fact, the person who closed the bug is not a member of Debian, nor is he in the NM process. Evidently he's just a random user who decided that old bugs offend him, so they should be closed.

So please, everyone, exercise a modicum of common sense when it comes to closing bug reports. This will keep the BTS useful for all of us and keep blood pressures at a reasonable level. :)

Blogger annoyingness


Two days ago, I noticed that a post from last year about my wallet getting stolen had attracted over 60 spams. So I went in, deleted all of them individually (because I can't select multiple comments to delete in Blogger), then closed comments on the post.

This morning, I caught up on my Planet Debian email, and discovered that Blogger had decided to make that post "new", so it showed up on Planet again! Argh!

So don't worry, I didn't lose my wallet again. Blogger is just nuts.

The virtues of limited terminal width


I've noticed that a great benefit of reading mail in an 80-column X terminal is that it acts as a simple filter: if a thread drifts so far to the right that I can no longer read the Subject: line, it's probably not worth my time to read it and I can kill the whole thing.

I wonder what sorts of gains in free time and productivity I could realize by shrinking my terminals to widths of 70, 60, or even 40 characters wide?