Fuckin' user interface design, I swear
I'm so old I can remember when forms were introducted to the
web; as you can imagine it was a big advance. The initial spec
included the usual text boxes, radio buttons, and so forth, two types
of “submit” buttons, and a “reset” button. Clicking “reset” would
reset the form contents to a defined initial state, normally empty.
So you'd have a bunch of form widgets, and then, at the bottom, a
Submit button, and next to it, a Reset button.
Even as an innocent youth, I realized this was a bad design. It is
just setting people up for failure. They might get the form all
filled out, be about to submit it, but click a few pixels off, hit the
Reset button by mistake, and have to start all over again.
Obviously, the Submit button should be over on the left, just under
the main form, where the user will visit it in due course after
dealing with the other widgets, and the Reset button should be way
over on the right, where it is less likely to be hit by accident.
(Or, more likely, it shouldn't be anywhere; in most cases it is
nothing but an attractive nuisance. How often does someone need to
reset the form anyway? How badly would they have to screw it up to
decide that it would be quicker to start over than to simply correct
their errors?)
Does my “obviously” come across as superior and condescending?
Honestly, it comes from a place of humility. My thinking is like this:
- The field of user inteface design is skilled work
- I have no training or experience in this field
- Also, I have no talent in design generally (Just look at this page!)
- Experience has proved that I am very stupid about this whole area
- But this particular problem is apparent even to a blockhead like me
- So it must be extremely obvious
But maybe I'm not giving myself enough credit. I said “obviously” but
it sure wasn't obvious to many people at the time. I remember 90% of
the forms I encountered having that Reset button at the bottom, at
least into the late 1990s.
And it's on my mind because my co-workers had a discussion about it at
work last week: don't put the Cancel button right next to the Submit
button. If this was obvious to dumbass me in 1994, why isn't it
common knowledge by now?
Don't put the Yes button right next to the No button. That
encourages mistakes. Obviously.
Don't put the commonly-used "close this window" keyboard shortcut
right next to the infrequently-used and irreversible "quit this
application" shortcut. In particular, don't put "close this window"
on control-W and "quit this application" on control-Q. I'm looking at
you, Firefox.
And that brings me to my real point. Can we talk about Google Meet?
These three buttons are at the bottom of the Google Meet
videoconferencing app. The left one temporarily mutes and unmutes the
microphone. The right one controls the camera similarly.
And if you click the button in between, you immediately leave the
meeting and quit the app.
Now, as I said I'm pretty damn stupid when it comes to design, but
geez, louise. Couldn't Google find someone less stupid than me?
[ Addendum 20210228: Google fucks up again. ]
[Other articles in category /tech]
permanent link
The ideal gas law
Katara is toiling through A.P. Chemistry this year. I never took
A.P. Chemistry but I did take regular high school chemistry and two
semesters of university chemistry so it falls to me to help her out when
things get too confusing. Lately she has been studying gas equilibria
and thermodynamics, in which the so-called
ideal gas law plays a central role: $$ PV=nRT$$
This is when you have a gas confined in a container of volume !!V!!.
!!P!! is the pressure exerted by the gas on the walls of the
container, the !!n!! is the number of gas particles, and the !!T!! is
the absolute temperature. !!R!! is a constant, called the “ideal gas
constant”. Most real gases do obey this law pretty closely, at least
at reasonably low pressures.
The law implies all sorts of interesting things. For example, if you
have gas in a container and heat it up so as to double the (absolute)
temperature, the gas would like to expand into twice the original
volume. If the container is rigid the pressure will double, but if
the gas is in a balloon, the balloon will double in size instead. Then if you
take the balloon up in an airplane so that the ambient pressure is
half as much, the balloon will double in size again.
I had seen this many times and while it all seems reasonable and makes
sense, I had never really thought about what it means. Sometimes
stuff in physics doesn't mean anything, but sometimes you can relate
it to a more fundamental law. For example, in The Character of
Physical Law, Feynman points out that the
Archimedean lever law is just an
expression of the law of conservation of energy, as applied to the
potential energy of the weights on the arms of the lever.
Thinking about the ideal gas law carefully, for the first time in my
life, I realized that it is also a special case of the law of
conservation of energy!
The gas molecules are zipping around with various energies, and this
kinetic energy manifests on the macro scale as as pressure (when they
bump into the walls of the container) and as volume (when they
bump into other molecules, forcing the other particles away.)
The pressure is measured in units of dimension !!\frac{\rm force}{\rm
area}!!, say newtons per square meter. The product !!PV!! of pressure and
volume is $$ \frac{\rm force}{\rm area}\cdot{\rm volume} = \frac{\rm
force}{{\rm distance}^2}\cdot{\rm distance}^3 = {\rm force}\cdot{\rm
distance} = {\rm energy}. $$ So the equation is equating two ways to
measure the same total energy of the gas.
Over on the right-hand side, we also have energy. The absolute
temperature !!T!! is the average energy per molecule and the !!n!!
counts the number of molecules; multiply them and you get the total
energy in a different way.
The !!R!! is nothing mysterious; it's just a proportionality constant
required to get the units to match up when we measure temperature in
kelvins and count molecules in moles. It's analogous to the mysterious
Cookie Constant that relates energy you have to expend on the
treadmill with energy you gain from eating cookies. The Cookie
Constant is !!1043 \frac{\rm sec}{\rm cookie}!!. !!R!! happens to be
around 8.3 joules per mole per kelvin.
(Actually I think there might be a bit more to !!R!! than I said,
something about the Boltzmann distribution in there.)
Somehow this got me and Katara thinking about what a mole of chocolate
chips would look like. “Better use those mini chips,” said Katara.
[Other articles in category /physics]
permanent link
Mystery twitter language
Today someone tweeted
about
an earlier blog article
of mine, saying
10° bir kvadratda ən böyük şəhərləri görə biləcəyiniz
bir xəritə olan bir sayt.
I looked at that and frowned, and said “What language is that? … is it
Azerbaijani?” And it is Azerbaijani!
Last time I encountered Azerbaijani I did
not recognize it. So I not only learned something last April, I
remembered it the following February when it came up again. Yay me!
[Other articles in category /lang]
permanent link
Paul L. Smith as Bluto
Yesterday I wondered who Robert Altman had cast as Bluto in
his 1980 live-action film Popeye. The answer turned
out to be Paul L. Smith, who seemingly was born
to play the part:
I have thought for years about how Shelley Duval was seemingly born to
play the part of Olive Oyl. (I remember the Mad magazine parody
making this observation at the time, and it wasn't funny because it
was so obvious.) I have somtimes wondered if Altman got the idea to
make a Popeye movie specifically so that he could cast Duval as
Olive Oyl.
Anyway, Paul L. Smith, who already looked like Bluto. He was in a
fair number of TV productions in the 70s and 80s, and I think it's
possible that I saw him in one or another one. But the only other
role of his that I remember clearly is from David Lynch's 1984
Dune. He plays Glossu “the Beast” Rabban.
Who in many ways is not that different from Bluto: Large, violent,
dangerous for his brutality but not his cunning.
Obviously the Baron wanted to cast Feyd-Rautha as Popeye, but events
got away from him and Paul became Popeye instead. In a
Dune-Popeye crossover I can see Alia as Swee'Pea. That means that
Chani has to be Olive, which I can live with.
The correspondence isn't perfect, of course. There is nobody in
Popeye like Lady Jessica or Stilgar. (Leto is obviously Poopdeck
Pappy.) On the other side, where is J. Wellington Wimpy? It's been a
while since I read the book, but I don't remember him appearing.
Reverend Mother Gaius Helen Mohiam is clearly the Sea Hag.
Me spinach musk flow! If ya controlsk the spinach, ya controlsk the uni-voice!
Ag-ag-ag-ag-ag!
[Other articles in category /misc]
permanent link
Down in the dumps
I was reading The Life and Prankes of
Long Meg of Westminster (1655),
which opens with the story of how Long Meg first came to London with a
posse of three or four girlfriends. After long travel they came
within sight of London, “which joyed their hearts greatly.” But as
they got closer, Meg's friends became less cheerful, and she said to
them:
What Lasses in a dumpe, and we so nigh London?
If someone had asked me to guess when “in a dump” or “in the dumps”
had been coined, I think I would have guessed sometime in the early
20th century. Nope! The Big Dictionary has cites back to 1535, which
is when Long Meg takes place. It also cites a 1785 dictionary for
“down in the dumps” specifically. The phrase is not connected with
the dump where you dump a load of trash, which is of much later
coinage.
It transpires that the lasses are in a dumpe because they realize that
time has come to pay the carrier who has helped transport them to
London, and believe he is likely to try to cheat them and take everything
they have. Meg says she will reason sweetly with the carrier, and if
that doesn't work, she will beat the crap out of him.
The carrier does try to take everything they have, but becomes
much more helpful after Meg has beaten him with a cudgel.
Here it is if you would like to read it yourself.
[Other articles in category /lang]
permanent link
More things that changed in later editions of Snow White
As you know, I've recently been looking into
the original version of Snow White
from 1812. ([1]
[2]) I knew that the 1812 version of
the Grimm stories was a lot rougher and more gruesome than the later
editions, but I missed many of the details. For example, in the later
versions, the evil queen orders her hunter to bring back Snow White's
liver and lungs as proof that he has murdered her. In the first
edition, she wants the liver and lungs so that she can eat them.
After Snow White is poisoned with the apple, the dwarfs put her in a
glass coffin. A prince happens by and begs them to give it to him,
which they do. In the later versions, the servants carrying away the
coffin stumble, the apple is dislodged from Snow White's throat, and
she returns to life.
In the original version, they get the coffin back to the prince's
palace without mishap. There the prince has the servants carry it
from room to room so that he can gaze at it always. (Ugh.)
Finally, the servants are so fed up with this that one of them takes
Snow White out of the coffin, stands her up, and, saying
We are plagued the whole day long, just because of such a dead girl
he clouts her in the back from pure spite.
The apple is dislodged, and Snow White marries the prince.
[Other articles in category /book]
permanent link
Hacking the git shell prompt
Git comes with
a very complicated shell function,, called
__git_ps1 ,
for interpolating Git information into your shell prompt. A typical
use would be:
PS1='>>> $(__git_ps1) :) '
PS1 is the variable that contains the shell's main prompt. Before
printing the prompt, the shell does variable and command interpolation
on this string. This means that if PS1 contains something like $(command
args...) , the shell replaces that string with the output from running
command args… . Here, it runs __git_ps1 and inserts the output into the
prompt. In the simplest case, __git_ps1 emits the name of the
currently-checked-out branch, so that the shell will actually print
this prompt:
>>> the-branch :)
But __git_ps1 has many other features besides. If you are in the middle
of a rebase or cherry-pick operation, it will emit something
like
the-branch|REBASE-i 1/5
or
the-branch|CHERRY-PICKING
instead. If HEAD is detached, it can still display the head
location in several formats. There are options to have the emitted string
indicate when the working tree is dirty and other things. My own
PS1 looks like this:
PS1='[$(_path) $(__git_ps1 "(%s)" )]> '
The _path command is something I
wrote to emit the path of the current working directory, abbreviated
in a contextually dependent way. It makes my prompt look like this:
[lib/app (the-branch)]>
Here lib/app is the path relative to the root of the repository.
The %s thing is an additional formatting instruction to __git_ps1 .
After it computes the description string, __git_ps1 inserts it into
"(%s)" in place of the %s , and emits the result of that
replacement. If you don't give __git_ps1 an argument, it uses "(%s) "
as a default, which has an extra space compared with what I have.
Lately I have been experimenting with appending .mjd.yyyymmdd to my
public branch names, to help me remember to delete my old dead
branches from the shared repository. This makes the branch names
annoyingly long:
gh1067-sort-dates-chronologically.mjd.20210103
gh1067-sort-dates-no-test.mjd.20210112
gh1088-cache-analysis-list.mjd.20210105
and these annoyingly long names appear in the output of __git_ps1 that is
inserted into my shell prompts.
One way to deal with this is to have the local branch names be
abbreviated and configure their upstream names to the long versions.
And that does work: I now have a little program called new-branch
that creates a new branch with the local short name, pushes it to the
long remote name, and sets the upstream. But I also wanted a generic
mechanism for abbreviating or transforming the branch name in the
prompt.
The supplied __git_ps1 function didn't seem to have an option
for that, or a callback for modifying the branch name before inserting
it into the prompt. I could have copied the function, modified the
parts I wanted, and used the modified version in place of the supplied
version, but it is 243 lines long, so I preferred not to do that.
But __git_ps1 does have one hook. Under the right circumstances,
it will attempt to colorize the prompt by inserting terminal
escape codes. To do this it invokes __git_ps_colorize_gitstring to
insert the escape codes into the various prompt components before it
assembles them. I can work with that!
The goal is now:
- Figure out how to tell
__git_ps1 to call __git_ps_colorize_gitstring
- Figure out how
__git_ps1 and __git_ps_colorize_gitstring communicate prompt components
- Write my own
__git_ps_colorize_gitstring to do something else
How to tell __git_ps1 to call __git_ps_colorize_gitstring
You have to do two things to get __git_ps1 to call the hook:
Set GIT_PS1_SHOWCOLORHINTS to some nonempty string. I set it to
true , which is a little deceptive, because false would have
worked as well.
Invoke __git_ps1 with two or more arguments.
Unfortunately, invoking the __git_ps1 with two or more arguments changes
its behavior in another way. It still computes a string, but it no
longer prints the string. Instead, it computes the string and
assigns it to PS1 . This means that
PS1="$(__git_ps arg arg….)"
won't work properly: the next time the shell wants to prompt, it will
evaluate PS1 , which will call __git_ps arg arg… , which will set
PS1 to some string like (the-branch) . Then the next time the
shell wants to print the prompt, it will evaluate PS1 , which will be
just some dead string like (the-branch) , with nothing in it to call
__git_ps1 again.
So we need to use a different shell feature. Instead of setting PS1
directly, we set PROMPT_COMMAND . This command is run before the
prompt is printed. Although this doesn't have anything to do directly
with the prompt, the command can change the prompt. If we set
PROMPT_COMMAND to invoke __git_ps1 , and if __git_ps1 modifies PS1 , the
prompt will change.
Formerly I had had this:
PS1='[$(_path) $(__git_ps1 "(%s)")]> '
but instead I needed to use:
GIT_PS1_SHOWCOLORHINTS=true
PROMPT_COMMAND='__git_ps1 "[$(_path) " " ] "' "(%s)"
Here __git_ps1 is getting three arguments:
"[$(_path) "
" ] "
"(%s)"
__git_ps1 computes its description of the Git state and inserts it into
the third argument in place of the %s . Then it takes the result of
this replacement, appends the first argument on the front and the
second on the back, and sets the prompt to the result. The shell will
still invoke _path in the course of evaluating the first string,
before passing it to __git_ps1 as an argument. Whew.
How __git_ps1 communicates prompt components to __git_ps_colorize_gitstring
The end result of all this rigamarole is that __git_ps1 is now being
called before every prompt, as before, but now it will also invoke
__git_ps_colorize_gitstring along the way. What does that actually get us?
The internals of __git_ps_colorize_gitstring aren't documented because I don't think this
is a planned use case, and __git_ps_colorize_gitstring isn't an advertised part of the
interface. __git_ps1 does something to construct the prompt, possibly
colorizing it in the process, but how it does the colorizing is
forbidden knowledge. From looking at the code I can see that the
colorizing is done by __git_ps_colorize_gitstring , and I needed to know what was going in
inside.
The (current) interface is that __git_ps1 puts the various components of
the prompts into a family of single-letter variables, which __git_ps_colorize_gitstring
modifies. Here's what these variables do, as best as I have been able
to ascertain:
b contains a description of the current HEAD, either the
current branch name or some other description
c indicates if you are in a bare repository
i indicates if changes have been recorded to the index
p contains information about whether the current head
is behind or ahead of its upstream branch
r describes the rebase / merge / cherry-pick state
s indicates if there is something in the stash
u indicates whether there are untracked files
w indicates whether the working tree is dirty
z is the separator between the branch name and the other indicators
Oddly, the one thing I wanted to change is the only one that __git_ps_colorize_gitstring
doesn't modify: the b variable that contains the name or
description of the current branch. Fortunately, it does exist and
there's nothing stopping me from writing a replacement __git_ps_colorize_gitstring that
does modify it.
Write a replacement for __git_ps_colorize_gitstring to do something else
So in the end all I needed was:
GIT_PS1_SHOWCOLORHINTS=true
PROMPT_COMMAND='__git_ps1 "[$(_path) " " ] "' "(%s)"
__git_ps1_colorize_gitstring () {
b=${b%%.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]}
b=${b%%.mjd}
}
The ${b%%PAT} thing produces the value of the variable b , except
that if the value ends with something matching the pattern PAT , that
part is removed. So the first assignment trims a trailing
.20210206 from the branch name, if there is one, and the second
trims off a trailing .mjd . If I wanted to trim off the leading gh
also I could use b=${b##gh} .
There's probably some way to use this in addition to the standard
__git_ps_colorize_gitstring , rather than in place of it. But I don't know how.
In conclusion
This was way harder to figure out than it should have been.
[Other articles in category /prog]
permanent link
We visit the town of Gap
Katara and I went to visit the town of Gap, PA. In
Gap there are so many eagles that they have these special bins for
getting rid of the extras.
[Other articles in category /misc]
permanent link
Hildebert and the mouse
This is the famous self-portrait of
Hildebert, a 12th century scribe in
what is now the Czech Republic. In this picture, Hildebert is shaking
his fist at a mouse, which is eating his lunch.
There is quite a lot going on here! First off, Hildebert is carrying
one of his quill pens behind his ear. This seems to me like a good
way to get ink in your hair, and I wonder if medieval scribes often
had smudges on their forheads.
I think the thing in his hand is a piece of bread. But what is on the
table? I think the mouse is eating Hildebert's cheese (we can see the
already-cut piece under the mouse's butt) and there seems to have been
a small roast bird of some type, which the mouse has upset but which
has not yet hit the floor. The table with the mouse is labeled Mensa
hildeberti, “Hildebert's table”, in case it was unclear just
whose lunch was being stolen.
Hildebert seems to be wearing a long garment with fancy matching
sleeves and collar, and over that what looks like a
chiton. I wonder if Hildebert really wore a
chiton?
On the left of the picture is a really interesting piece of equipment.
Until I saw this picture, it had never occurred to me that the lap
desk had been invented before I was born. But here it is, almost nine
hundred years ago. And it certainly is a lap desk, having no legs.
In this picture the lap desk is supported by a backward-headed lion,
but in actual practice such luxuries are probably hard to come by, so
Hildebert would have put the desk on his lap.
The two long curvy things on the left edge of the lap desk are not
legs. They are inkhorns: sawn-off animal horns, filled with ink.
When you need to get more ink on your quill, you dip the end in the
inkhorn. I had heard of inkhorns but until I saw this picture I had
never understood how you used them: they won't stand up, and if you
lay them down the ink will spill. But Hildebert's picture makes it
perfectly clear: the lap desk has a couple of round holes in it, and
you slide the inkhorns into the holes until they stop. Very nice!
Next to the inkhorns are two extra quills, and along the bottom edge
of the lap desk there is a ridge to keep the paper or parchment from
sliding into your lap. I am pretty sure that the lion is holding the
desk by the bottom edge, so that it is presented to Hildebert
sideways. Hildebert is too enraged by the mouse to care about this.
Also on the desk is a booklet, in which (according to Wikipedia) Hildebert has written:
Pessime mus, saepius me provocas ad iram. Ut te deus perdat
I think I can make this out. (Medieval scribes used a great many
abbreviations. For example, iram is written as “irã”. Similarly,
the hildeberti above the table is abbreviated to “hildebti”. If you
are interested,
I discussed scribal abbreviations a couple of years ago.)
Wikipedia's translation of this is:
Most wicked mouse, you incite me to anger once too often. May God
destroy you.
I think the phrasing and the fist-shaking, directed at a mouse, are
meant by Hildebert to be a humorous overreaction.
Underneath Hildebert is a drawing of his colleague Everwin
(EVERWINVS). Everwin seems to be painting some sort of decoration
with a brush. Check out his fancy sleeves and matching socks!
I am not sure what Hildebert is holding in his left hand or whether it
intersects the lion's arm. My best
guess is that it is Hildebert's table knife, and that the picture
means to show it passing in front of the lion, not intersecting the
lion.
Many thanks to Marnanel Thurman for bringing this to my attention.
[Other articles in category /art]
permanent link
The magic mirror in Snow White
A few weeks ago
I was thinking about Snow White and
in the course of doing that I looked up
the original German version of 1812.
(Snow White herself is
story #53, on page 238.)
The magic mirror is introduced this way:
Die Königin … hatte auch einen Spiegel, vor trat sie alle Morgen und
fragte: …
(“The queen… also had a mirror, before which she stood every morning
and asked…”)
The mirror is simply einen Spiegel, a mirror, not a specifically
magic mirror. That seems to have been a later interpolation. In
the 1857 edition, it says Sie hatte einen wunderbaren Spiegel….
There is no wunderbaren in the original.
I prefer the original. The mirror recites poetry; to say it is a magic
mirror is superfluous.
But on second thought, is it? There is another explanation: in the
original version, perhaps the mirror is an ordinary one, and the queen is
psychotic.
Certainly nobody else hears the mirror speaking. And the queen
tells the hunter not only to kill Snow White in the forest, but to
bring back Snow White's lungs and liver, so that the she may eat them.
With salt! (die will ich mit Salz kochen und essen.) Now I prefer
the original even more. The later version, which unequivocally states
that the mirror is magic, is much less terrifying.
I suppose the argument against this reading is that the mirror also
provides the queen with real information: Snow White is still alive,
and living with the seven dwarfs. I think the original text does
imply that the queen was aware of the seven dwarfs, but how might she
have known that Snow White was still alive? Well, she did eat the
lungs and liver, which had actually come from a young wild boar
(junger Frischling). Perhaps she was satisfied at first, but then
there was something about the taste, or the texture, not quite what she
expected… it gnawed at her for hours, and then in a flash of rage she
realized what she had actually eaten…
[ Addendum 20210202: In case you wanted to see it, Note, by the way, that in 1812 the umlaut marks in Königin etc. still looked like small letter ‘e’; they had not yet been reduced to diareses. ]
[ Addendum 20210207: another startling detail
that was revised in the later editions. ]
[ Addendum 20210321: The more I think about the queen's psychosis, the more obvious it seems that this is the correct explanation. ]
[Other articles in category /book]
permanent link
|