Shallow Thoughts : : Dec
Akkana's Musings on Open Source Computing and Technology, Science, and Nature.
Thu, 31 Dec 2015
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.
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: house, snow
[
11:28 Dec 31, 2015
More nature |
permalink to this entry |
]
Sun, 27 Dec 2015
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):
- Open another terminal window and run
ps aux | grep apt
to find the apt-get dist-upgrade process and kill it.
(sudo pkill apt-get
is probably an easier approach.)
Ensure that apt has exited and there's a shell prompt in the window
where the scary blue extlinux warning was.
echo "extlinux hold" | dpkg --set-selections
apt-get dist-upgrade
and wait forever for all the
packages to install
aptitude search linux-image | grep '^i'
to find out
what kernel versions are installed. Pick one. I picked 3.14-2-686-pae
because that happened to be the same kernel I was already running,
from Sid.
ls -l /boot
and make sure that kernel is there,
along with an initrd.img of the same version.
- Edit /boot/extlinux/extlinux.conf and find the stanza
for the Jessie boot. Edit the kernel and append initrd
lines to use the right kernel version.
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: linux, debian, extlinux
[
17:28 Dec 27, 2015
More linux/install |
permalink to this entry |
]
Sun, 20 Dec 2015
Yesterday was the Los Alamos Christmas Bird Count.
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.)
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.
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: nature, birds
[
14:21 Dec 20, 2015
More nature/birds |
permalink to this entry |
]
Sat, 12 Dec 2015
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: editors, emacs
[
14:48 Dec 12, 2015
More linux/editors |
permalink to this entry |
]
Fri, 04 Dec 2015
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: zsh, shell, regexp, gimp, programming
[
13:25 Dec 04, 2015
More linux/cmdline |
permalink to this entry |
]