Shallow Thoughts : : Dec

Akkana's Musings on Open Source Computing and Technology, Science, and Nature.

Thu, 31 Dec 2015

Weather musing, and poor insulation

It's lovely and sunny today. I was just out on the patio working on some outdoor projects; I was wearing a sweatshirt, but no jacket or hat, and the temperature seemed perfect.

Then I came inside to write about our snowstorm of a few days ago, and looked up the weather. NOAA reports it's 23°F at Los Alamos airport, last reading half an hour ago. Our notoriously inaccurate (like every one we've tried) outdoor digital thermometer says it's 26°.

Weather is crazily different here. In California, we were shivering and miserable when the temperature dropped below 60°F. We've speculated a lot on why it's so different here. The biggest difference is probably that it's usually sunny here. In the bay area, if the temperature is below 60°F it's probably because it's overcast. Direct sun makes a huge difference, especially the sun up here at 6500-7500' elevation. (It feels plenty cold at 26°F in the shade.) The thin, dry air is probably another factor, or two other factors: it's not clear what's more important, thin, dry, or both.

We did a lot of weather research when we were choosing a place to move. We thought we'd have trouble with snowy winters, and would probably want to take vacations in winter to travel to warmer climes. Turns out we didn't know anything. When we were house-hunting, we went for a hike on a 17° day, and with our normal jackets and gloves we were fine. 26° is lovely here if you're in the sun, and the rare 90° summer day, so oppressive in the Bay Area, is still fairly pleasant if you can find some shade.

But back to that storm: a few days ago, we had a snowstorm combined with killer blustery winds. The wind direction was whipping around, coming from unexpected directions -- we never get north winds here -- and it taught us some things about the new house that we hadn't realized in the nearly two years we've lived here.

[Snow coming under the bedroom door] For example, the bedroom was cold. I mean really cold. The windows on the north wall were making all kinds of funny rattling noises -- turned out some of them had leaks around their frames. There's a door on the north wall, too, that leads out onto a deck, and the area around that was pretty cold too, though I thought a lot of that was leakage through the air conditioner (which had had a cover over it, but the cover had already blown away in the winds). We put some towels around the base of the door and windows.

Thank goodness for lots of blankets and down comforters -- I was warm enough overnight, except for cold hands while reading in bed. In the morning, we pulled the towel away from the door, and discovered a small snowdrift inside the bedroom.

We knew the way that door was hung was fairly hopeless -- we've been trying to arrange for a replacement, but in New Mexico everything happens mañana -- but snowdrifts inside the room are a little extreme.

We've added some extra weatherstripping for now, and with any luck we'll get a better-hung door before the next rare north-wind snowstorm. Meanwhile, I'm enjoying today's sunshine while watching the snow melt in the yard.

Tags: ,
[ 11:28 Dec 31, 2015    More nature | permalink to this entry | comments ]

Sun, 27 Dec 2015

Extlinux on Debian Jessie

Debian "Sid" (unstable) stopped working on my Thinkpad X201 as of the last upgrade -- it's dropping mouse and keyboard events. With any luck that'll get straightened out soon -- I hear I'm not the only one having USB problems with recent Sid updates. But meanwhile, fortunately, I keep a couple of spare root partitions so I can try out different Linux distros. So I decided to switch to the current Debian stable version, "Jessie".

The mouse and keyboard worked fine there. Except it turned out I had never fully upgraded that partition to the "Jessie"; it was still on "Wheezy". So, with much trepidation, I attempted an apt-get update; apt-get dist-upgrade

After an interminable wait for everything to download, though, I was faced with a blue screen asking this:

No bootloader integration code anymore.
The extlinux package does not ship bootloader integration anymore.
If you are upgrading to this version of EXTLINUX your system will not boot any longer if EXTLINUX was the only configured bootloader.
Please install GRUB.
<Ok>

No -- it's not okay! I have good reasons for not using grub2 -- besides which, extlinux on exact machine has been working fine for years under Debian Sid. If it worked on Wheezy and works on Sid, why wouldn't it work on the version in between, Jessie?

And what does it mean not to ship "bootloader integration", anyway? That term is completely unclear, and googling was no help. There have been various Debian bugs filed but of course, no explanation from the developers for exactly what does and doesn't work.

My best guess is that what Debian means by "bootloader integration" is that there's a script that looks at /boot/extlinux/extlinux.conf, figures out which stanza corresponds to the current system, figures out whether there's a new kernel being installed that's different from the one in extlinux.conf, and updates the appropriate kernel and initrd lines to point to the new kernel.

If so, that's something I can do myself easily enough. But what if there's more to it? What would actually happen if I upgraded the extlinux package?

Of course, there's zero documentation on this. I found plenty of questions from people who had hit this warning, but most were from newbies who had no idea what extlinux was or why their systems were using it, and they were advised to install grub. I only found one hit from someone who was intentionally using extlinux. That person aborted the install, held back the package so the potentially nonbooting new version of extlinux wouldn't be installed, then updated extlinux.conf by hand, and apparently that worked fine.

It sounded like a reasonable bet. So here's what I did (as root, of course):

It worked fine. I booted into jessie with the kernel I had specified. And hooray -- my keyboard and mouse work, so I can continue to use my system until Sid becomes usable again.

Tags: , ,
[ 17:28 Dec 27, 2015    More linux/install | permalink to this entry | comments ]

Sun, 20 Dec 2015

Christmas Bird Count

Yesterday was the Los Alamos Christmas Bird Count.

[ Mountain chickadee ] No big deal, right? Most counties have a Christmas Bird Count, a specified day in late December when birders hit the trails and try to identify and count as many birds as they can find. It's coordinated by the Audubon Society, which collects the data so it can be used to track species decline, changes in range in response to global warming, and other scientific questions. The CBC has come a long way from when it split off from an older tradition, the Christmas "Side Hunt", where people would hit the trails and try to kill as many animals as they could.

But the CBC is a big deal in Los Alamos, because we haven't had one since 1953. It turns out that to run an official CBC, you have to be qualified by Audubon and jump through a lot of hoops proving that you can do it properly. Despite there being a very active birding community here, nobody had taken on the job of qualifying us until this year. There was a lot of enthusiasm for the project: I think there were 30 or 40 people participating despite the chilly, overcast weather.

The team I was on was scheduled to start at 7. But I had been on the practice count in March (running a practice count is one of the hoops Audubon makes you jump through), and after dragging myself out of bed at oh-dark-thirty and freezing my toes off slogging through the snow, I had learned that birds are mostly too sensible to come out that early in winter. I tried to remind the other people on the team of what the March morning had been like, but nobody was listening, so I said I'd be late, and I met them at 8. (Still early for me, but I woke up early that morning.)

[ Two very late-season sandhill cranes ] Sure enough, when I got there at 8, there was disappointment over how few birds there were. But actually that continued all day: the promised sun never came out, and I think the birds were hoping for warmer weather. We did see a good assortment of woodpeckers and nuthatches in a small area of Water Canyon, and later, a pair of very late-season sandhill cranes made a low flyover just above where we stood on Estante Way; but mostly, it was disappointing.

In the early afternoon, the team disbanded to go home and watch our respective feeders, except for a couple of people who drove down the highway in search of red-tailed hawks and to the White Rock gas station in search of rock pigeons. (I love it that I'm living in a place where birders have to go out of their way to find rock pigeons to count.)

I didn't actually contribute much on the walks. Most of the others were much more experienced, so mostly my role was to say "Wait, what's that noise?" or "Something flew from that tree to this one" or "Yep, sure enough, two more juncos." But there was one species I thought I could help with: scaled quail. We've been having a regular flock of scaled quail coming by the house this autumn, sometimes as many as 13 at a time, which is apparently unusual for this time of year. I had Dave at home watching for quail while I was out walking around.

When I went home for a lunch break, Dave reported no quail: there had been a coyote sniffing around the yard, scaring away all the birds, and then later there'd been a Cooper's hawk. He'd found the hawk while watching a rock squirrel that was eating birdseed along with the towhees and juncos: the squirrel suddenly sat up and stared intently at something, and Dave followed its gaze to see the hawk perched on the fence. The squirrel then resumed eating, having decided that a Cooper's hawk is too small to be much danger to a squirrel.

[ Scaled quail ] But what with all the predators, there had been no quail. We had lunch, keeping our eyes on the feeder area, when they showed up. Three of them, no, six, no, nine. I kept watch while Dave went over to another window to see if there were any more headed our way. And it turns out there was a whole separate flock, nine more, out in the yard. Eighteen quail in all, a record for us! We'd suspected that we had two different quail families visiting us, but when you're watching one spot with quail constantly running in and out, there's no way to know if it's the same birds or different ones. It needed two people watching different areas to get our high count ot 18. And a good thing: we were the only bird counters in the county who saw any quail, let alone eighteen. So I did get to make a contribution after all.

I carried a camera all day, but my longest regular lens (a 55-250 f/4-5.6) isn't enough when it comes to distant woodpeckers. So most of what I got was blurry, underexposed "record shots", except for the quail, cranes, and an obliging chickadee who wasn't afraid of a bunch of binocular-wielding anthropoids. Photos here: Los Alamos Christmas Bird Count, White Rock team, 2015.

Tags: ,
[ 14:21 Dec 20, 2015    More nature/birds | permalink to this entry | comments ]

Sat, 12 Dec 2015

Emacs rich-text mode: coloring and styling plain text

I use emacs a lot for taking notes, during meetings, while watching lectures in a MOOC, or while researching something.

But one place where emacs falls short is highlighting. For instance, if I paste a section of something I'm researching, then I want to add a comment about it, to differentiate the pasted part from my added comments, I have to resort to horrible hacks like "*********** My comment:". It's like the stuff Outlook users put in emails because they can't figure out how to quote.

What I really want is a simple rich-text mode, where I can highlight sections of text by changing color or making it italic, bold, underlined.

Enter enriched-mode. Start it with M-x enriched-mode and then you can apply some styles with commands like M-o i for italic, M-o b for bold, etc. These styles may or may not be visible depending on the font you're using; for instance, my font is already bold and emacs isn't smart enough to make it bolder, the way some programs are. So if one style doesn't work, try another one.

Enriched mode will save these styles when you save the file, with a markup syntax like <italic>This text is in italic.</italic> When you load the file, you'll just see the styles, not the markup.

Colors

But they're all pretty subtle. I still wanted colors, and none of the documentation tells you much about how to set them.

I found a few pages saying that you can change the color of text in an emacs buffer using the Edit menu, but I hide emacs's menus since I generally have no use for them: emacs can do everything from the keyboard, one of the things I like most about it, so why waste space on a menu I never use? I do that like this:

(tool-bar-mode 0)
(menu-bar-mode 0)

It turns out that although the right mouse button just extends the selection, Control-middleclick gives a context menu. Whew! Finally a way to change colors! But it's not at all easy to use: Control-middleclick, mouse over Foreground Color, slide right to Other..., click, and the menu goes away and now there's a prompt in the minibuffer where you can type in a color name.

Colors are saved in the file with a syntax like: <x-color><param>red</param>This text is in red.</x-color>

All that clicking is a lot of steps, and requires taking my hands off the keyboard. How do I change colors in an easier, keyboard driven way? I drew a complete blank with my web searches. A somewhat irritable person on #emacs eventually hinted that I should be using overlays, and I eventually figured out how to set overlay colors ((overlay-put (make-overlay ...)) turned out to be the way to do that) but it was a complete red herring: enriched-mode doesn't pay any attention to overlay colors. I don't know what overlays are useful for, but it's not that.

But in emacs, you can find out what's bound to a key with describe-key. Maybe that works for mouse clicks too? I ran describe-key, held down Control, clicked the middle button -- the context menu came up -- then navigated to Foreground Color and Other... and discovered that it's calling (facemenu-set-foreground COLOR &optional START END).

Binding to keys

Finally, a function I can bind to a key! COLOR is just a string, like "red". The documentation implies that START and END are optional, and that the function will apply to the selected region if there is one. But in practice, if you don't specify START and END, nothing happens, so you have to specify them. (region-beginning) and (region-end) work if you have a selected region.

Similarly, I learned that Face->italic from that same menu calls (facemenu-set-italic), and likewise for bold, underline etc. They work on the selected region.

But what if there's no region defined? I decided it might be nice to be able to set styles for the current line, without selecting it first. I can use (line-beginning-position) and (line-end-position) for START and END. So I wrote a wrapper function. For that, I didn't want to use specific functions like (facemenu-set-italic); I wanted to be able pass a property like "italic" to my wrapper function.

I found a way to do that: (put-text-property START END 'italic). But that wasn't quite enough, because put-text-property replaces all properties; you can't make something both italic and bold. To add a property without removing existing ones, use (add-text-properties START END (list 'face 'italic)).

So here's the final code that I put in my .emacs. I was out of excuses to procrastinate, and my enriched-mode bindings worked fine for taking notes on the project which had led to all this procrastination.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Text colors/styles. You can use this in conjunction with enriched-mode.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

;; rich-style will affect the style of either the selected region,
;; or the current line if no region is selected.
;; style may be an atom indicating a rich-style face,
;; e.g. 'italic or 'bold, using
;;   (put-text-property START END PROPERTY VALUE &optional OBJECT)
;; or a color string, e.g. "red", using
;;   (facemenu-set-foreground COLOR &optional START END)
;; or nil, in which case style will be removed.
(defun rich-style (style)
  (let* ((start (if (use-region-p)
                    (region-beginning) (line-beginning-position)))
                    
         (end   (if (use-region-p)
                    (region-end)  (line-end-position))))
    (cond
     ((null style)      (set-text-properties start end nil))
     ((stringp style)   (facemenu-set-foreground style start end))
     (t                 (add-text-properties start end (list 'face style)))
     )))

(defun enriched-mode-keys ()
  (define-key enriched-mode-map "\C-ci"
    (lambda () (interactive)    (rich-style 'italic)))
  (define-key enriched-mode-map "\C-cB"
    (lambda () (interactive)    (rich-style 'bold)))
  (define-key enriched-mode-map "\C-cu"
    (lambda () (interactive)    (rich-style 'underline)))
  (define-key enriched-mode-map "\C-cr"
    (lambda () (interactive)    (rich-style "red")))
  ;; Repeat for any other colors you want from rgb.txt

  (define-key enriched-mode-map (kbd "C-c ")
    (lambda () (interactive)    (rich-style nil)))
  )
(add-hook 'enriched-mode-hook 'enriched-mode-keys)

Tags: ,
[ 14:48 Dec 12, 2015    More linux/editors | permalink to this entry | comments ]

Fri, 04 Dec 2015

Distclean part 2: some useful zsh tricks

I wrote recently about a zsh shell function to run make distclean on a source tree even if something in autoconf is messed up. In order to save any arguments you've previously passed to configure or autogen.sh, my function parsed the arguments from a file called config.log.

But it might be a bit more reliable to use config.status -- I'm guessing this is the file that make uses when it finds it needs to re-run autogen.sh. However, the syntax in that file is more complicated, and parsing it taught me some useful zsh tricks.

I can see the relevant line from config.status like this:

$ grep '^ac_cs_config' config.status
ac_cs_config="'--prefix=/usr/local/gimp-git' '--enable-foo' '--disable-bar'"

--enable-foo --disable-bar are options I added purely for testing. I wanted to make sure my shell function would work with multiple arguments.

Ultimately, I want my shell function to call autogen.sh --prefix=/usr/local/gimp-git --enable-foo --disable-bar The goal is to end up with $args being a zsh array containing those three arguments. So I'll need to edit out those quotes and split the line into an array.

Sed tricks

The first thing to do is to get rid of that initial ac_cs_config= in the line from config.status. That's easy with sed:

$ grep '^ac_cs_config' config.status | sed -e 's/ac_cs_config=//'
"'--prefix=/usr/local/gimp-git' '--enable-foo' '--disable-bar'"

But since we're using sed anyway, there's no need to use grep to get the line: we can do it all with sed. First try:

sed -n '/^ac_cs_config/s/ac_cs_config=//p' config.status

Search for the line that starts with ac_cs_config (^ matches the beginning of a line); then replace ac_cs_config= with nothing, and p print the resulting line. -n tells sed not to print anything except when told to with a p.

But it turns out that if you give a sed substitution a blank pattern, it uses the last pattern it was given. So a more compact version, using the search pattern ^ac_cs_config, is:

sed -n '/^ac_cs_config=/s///p' config.status

But there's also another way of doing it:

sed '/^ac_cs_config=/!d;s///' config.status

! after a search pattern matches every line that doesn't match the pattern. d deletes those lines. Then for lines that weren't deleted (the one line that does match), do the substitution. Since there's no -n, sed will print all lines that weren't deleted.

I find that version more difficult to read. But I'm including it because it's useful to know how to chain several commands in sed, and how to use ! to search for lines that don't match a pattern.

You can also use sed to eliminate the double quotes:

sed '/^ac_cs_config=/!d;s///;s/"//g' config.status
'--prefix=/usr/local/gimp-git' '--enable-foo' '--disable-bar'
But it turns out that zsh has a better way of doing that.

Zsh parameter substitution

I'm still relatively new to zsh, but I got some great advice on #zsh. The first suggestion:

sed -n '/^ac_cs_config=/s///p' config.status | IFS= read -r; args=( ${(Q)${(z)${(Q)REPLY}}} ); print -rl - $args

I'll be using final print -rl - $args for all these examples: it prints an array variable with one member per line. For the actual distclean function, of course, I'll be passing the variable to autogen.sh, not printing it out.

First, let's look at the heart of that expression: the args=( ${(Q)${(z)${(Q)REPLY}}}.

The heart of this is the expression ${(Q)${(z)${(Q)x}}} The zsh parameter substitution syntax is a bit arcane, but each of the parenthesized letters does some operation on the variable that follows.

The first (Q) strips off a level of quoting. So:

$ x='"Hello world"'; print $x; print ${(Q)x}
"Hello world"
Hello world

(z) splits an expression and stores it in an array. But to see that, we have to use print -l, so array members will be printed on separate lines.

$ x="a b c"; print -l $x; print "....."; print -l ${(z)x}
a b c
.....
a
b
c

Zsh is smart about quotes, so if you have quoted expressions it will group them correctly when assigning array members:

$ 
x="'a a' 'b b' 'c c'"; print -l $x; print "....."; print -l ${(z)x} 'a a' 'b b' 'c c' ..... 'a a' 'b b' 'c c'

So let's break down the larger expression: this is best read from right to left, inner expressions to outer.

${(Q) ${(z) ${(Q) x }}}
   |     |     |   \
   |     |     |    The original expression, 
   |     |     |   "'--prefix=/usr/local/gimp-git' '--enable-foo' '--disable-bar'"
   |     |     \
   |     |      Strip off the double quotes:
   |     |      '--prefix=/usr/local/gimp-git' '--enable-foo' '--disable-bar'
   |     \
   |      Split into an array of three items
   \
    Strip the single quotes from each array member,
    ( --prefix=/usr/local/gimp-git --enable-foo --disable-bar )
Neat!

For more on zsh parameter substitutions, see the Zsh Guide, Chapter 5: Substitutions.

Passing the sed results to the parameter substitution

There's still a little left to wonder about in our expression, sed -n '/^ac_cs_config=/s///p' config.status | IFS= read -r; args=( ${(Q)${(z)${(Q)REPLY}}} ); print -rl - $args

The IFS= read -r seems to be a common idiom in zsh scripting. It takes standard input and assigns it to the variable $REPLY. IFS is the input field separator: you can split variables into words by spaces, newlines, semicolons or any other character you want. IFS= sets it to nothing. But because the input expression -- "'--prefix=/usr/local/gimp-git' '--enable-foo' '--disable-bar'" -- has quotes around it, IFS is ignored anyway.

So you can do the same thing with this simpler expression, to assign the quoted expression to the variable $x. I'll declare it a local variable: that makes no difference when testing it in the shell, but if I call it in a function, I won't have variables like $x and $args cluttering up my shell afterward.

local x=$(sed -n '/^ac_cs_config=/s///p' config.status); local args=( ${(Q)${(z)${(Q)x}}} ); print -rl - $args

That works in the version of zsh I'm running here, 5.1.1. But I've been warned that it's safer to quote the result of $(). Without quotes, if you ever run the function in an older zsh, $x might end up being set only to the first word of the expression. Second, it's a good idea to put "local" in front of the variable; that way, $x won't end up being set once you've returned from the function. So now we have:

local x="$(sed -n '/^ac_cs_config=/s///p' config.status)"; local args=( ${(Q)${(z)${(Q)x}}} ); print -rl - $args

You don't even need to use a local variable. For added brevity (making the function even more difficult to read! -- but we're way past the point of easy readability), you could say:

args=( ${(Q)${(z)${(Q)"$(sed -n '/^ac_cs_config=/s///p' config.status)"}}} ); print -rl - $args
or even
print -rl - ${(Q)${(z)${(Q)"$(sed -n '/^ac_cs_config=/s///p' config.status)"}}}
... but that final version, since it doesn't assign to a variable at all, isn't useful for the function I'm writing.

Tags: , , , ,
[ 13:25 Dec 04, 2015    More linux/cmdline | permalink to this entry | comments ]