Vim :ruby and :rubydo scope

Note to self. In old Vim (tested in 7.2.320), I could do this:

:ruby x='foo'
:rubydo $_=x

Now every line in the file says foo. But in Vim 7.3 I get an error:

NameError: undefined local variable or method `x' for main:Object

The scoping rules for Ruby in Vim must have changed somewhere along the line. I was abusing this feature to do some handy things, so this is sad.

A workaround is to use global variables in Ruby instead. So this still works:

:ruby $x='foo'
:rubydo $_=$x

Phew.

August 31, 2010 @ 10:40 AM PDT
Cateogory: Programming
Tags: Ruby, Vim

Emacs undo trees

I've said it before: undo in Emacs is horrible. On the other hand, undo in Vim is awesome.

But this is true no longer. Now there are undo trees for Emacs! Yes, this news is so important I had to italicize and bold it. It's like Emacs has been punching me in the face for years, and today I got it to stop. I never thought I'd see the day.

And it works great too. You can even view the tree visually and navigate it with the cursor keys, which is a step up on what Vim offers out of the box.

Emacs undo trees

In other news, Vim 7.3 is out and it now has persistent undo across reloads. It's like an arms race, and gleeful hackers reap the benefits.

August 17, 2010 @ 2:06 PM PDT
Cateogory: Programming
Tags: Emacs, Vim, Undo

Let's draw some pixels

I've been getting into pixel art a lot lately. It appeals to me on a lot of levels.

The coder in me likes it because it's so precise. Every pixel is placed just so. The color palette is limited to a dozen colors. Building a drawing out of such limited means reminds me of building programs out of primitives. There are design patterns in pixel art: dithering, manual anti-aliasing. There are abstractions that work and abstractions that don't. There's a lot of goofing around with RGB values and transparency settings; it's perhaps the most deeply computer-based art form you could come up with, and as a deeply computer-based human, I really like it.

The gamer in me is still partly stuck in the early 90's, so it's a huge injection of nostalgia to look at pixel art. NES- and SNES-era games had a charm that is unmatched by anything since. And I don't think that's entirely nostalgia talking; I still play old games and they're still so much fun. And the art in a lot of those games was just darned good. If you stop and look at it really carefully, and start to get an understanding of how it was made, you can't help but be impressed.

The "artist" in me (if there is such a thing in my brain somewhere) is blown away by some of the things good pixel artists can produce. Go look at foolstown.com and try not to slobber. Some of this stuff just looks amazing. Not "good for a pixel drawing", but good on a level anyone could appreciate.

Pixel doodles are also good practice for the RPG my wife and I are still ever-so-slowly creating. Creating art and music for a game are turning out to be much harder work than programming it.

In any case, I drew a cow standing beside a tree. And I made a new pixel art page to house my admittedly still-amateurish drawings.

Cow Tree

August 10, 2010 @ 11:19 AM PDT
Cateogory: Art

Review: What Do You Care What Other People Think?

I recently reviewed Surely You're Joking, Mr. Feynman!. It was good enough that I had to get the sequel.

What Do You Care What Other People Think? is another collection of stories and anecdotes written by and/or about Richard Feynman. A bit in contrast to the first book, rather than a chronological series of anecdotes, this book focuses on a couple of main topics.

Feynman discusses his first wife in some detail. Of particular interest, he describes his and his wife's brutal devotion to honesty in their relationship, even in the face of highly unpleasant truths (terminal disease, in this case). It's the honesty of a scientist, carried into "everyday" life. This was bittersweet for me to read, because the story has a sad ending.

There is also a short series of letters from Feynman to others, where he discusses the silliness of pomp and circumstance, e.g. his foibles and breaches of protocol when meeting some king or other. As someone who hates ceremony, I got a huge kick out of these.

A large part of the book is devoted to discussing the Presidential Commission which investigated the cause of the Challenger shuttle disaster. Feynman's full report is included in the book as well.

As someone interested in astronomy and space flight (and who isn't interested in those?) I found this fascinating. There's a lot of behind-the-scenes stuff. Engineers are painted in a good light, managers and politicians not so much. (Software engineers come out looking especially good, which made me feel (unjustifiably) good about myself by proxy.) There are some diagrams and a lot of technical discussion of the shuttle. Not so much that it drowns the narrative, but enough that I'm probably going to spend the next week reading Wikipedia on the subject now.

Feynman explains his simple methods at getting to the truth in the investigation. Go talk to the guys who put things together. Get your hands on some O-ring rubber and test its resistance to temperature yourself in a glass of ice water. Cut to the heart of the matter. It's good stuff.

Ultimately, as you know if you've read the report, Feynman rips NASA apart, showing that they were fooling themselves into believing the shuttle was safer than it really was. The last sentence of the report says everything: "Nature cannot be fooled."

The last section of the book discusses the value of science. More specifically, Feynman discusses the value of doubt. I very much liked how the chapter ends:

It is our responsibility as scientists , knowing the great progress which comes from a satisfactory philosophy of ignorance, the great progress which is the fruit of freedom of thought, to proclaim the value of this freedom; to teach how doubt is not to be feared but welcomed and discussed; and to demand this freedom as our duty to all coming generations.

If there's one trait I had to pick to separate good people from bad, it would be the ability to admit being wrong. And if I had to separate the good from the excellent, it would be not just the ability to admit being wrong, but the eagerness to be proved wrong.

There's a certain kind of devotion to the truth that not many people achieve, and maybe not many people even want to achieve. There's comfort in thinking that you know things. It's very tempting. I think it's probably partly why most people are religious. I suspect it's a big reason why so many people are so stubbornly wrong about so many things in general. I suspect this comfort is an enormous source of suffering in the world.

But there's another kind of comfort that people miss out on. It's the comfort of knowing that although you're probably wrong about a lot of things, you're trying your hardest to be right. You pay the price of being aware of your own state of ignorance, but you can rest a bit easier knowing that you're maybe, hopefully, inching towards the truth. I never heard the word "freedom" used to describe this feeling before, as Feynman does above, but it fits.

That's why I like reading about Feynman and reading Feynman's words. He seemed to live this philosophy as well as anyone could hope to.

August 06, 2010 @ 10:12 PM PDT
Cateogory: Book Reviews

X automation with xte

I learned today (via a great blog post) about xte. This program lets you simulate X Windows mouse and keyboard events from the commandline. How much more awesome can you get?

Hans illustrates how to integrate xbindkeys and xte to make KDE4 effects activate. I wanted the KDE4 "Desktop Grid" to appear when I press a mouse button (because my new mouse has a lot of buttons to spare), so this is exactly what I was looking for.

xte is the kind of glue that makes Linux awesome. KDE lets you set global keyboard shortcuts for lots of things. xbindkeys lets you assign shell commands to mouse buttons. And xte ties the two together. Possibly none of the programmers on these three tools knew about the others, but they interact perfectly to let you do anything you want.

You may be thinking, "If you want to work with KDE from the commandline, why not use DBUS?" That's what I tried to do first. But I can't for the life of me figure it out. There's some indication that we might be able to do this somday, like so:

qdbus org.kde.kglobalaccel /component/kwin org.kde.kglobalaccel.Component.invokeShortcut ShowDesktopGrid

Or maybe it's already in the latest version of KDE and I haven't upgraded yet. Either way.

By the way: could DBUS possibly have a more verbose or cryptic interface? I was hunting through the available DBUS commands looking for something that would show the Desktop Grid, and I ended up having to scan through lists of crap like this:

~ % qdbus org.kde.kwin /KWin                         
method Q_NOREPLY void org.kde.KWin.cascadeDesktop()
method void org.kde.KWin.circulateDesktopApplications()
method bool org.kde.KWin.compositingActive()
signal void org.kde.KWin.compositingToggled(bool active)
method int org.kde.KWin.currentDesktop()
method QList<int> org.kde.KWin.decorationSupportedColors()
method void org.kde.KWin.doNotManage(QString name)
method Q_NOREPLY void org.kde.KWin.killWindow()
method QStringList org.kde.KWin.listOfEffects()
method void org.kde.KWin.loadEffect(QString name)
method QStringList org.kde.KWin.loadedEffects()
method void org.kde.KWin.nextDesktop()
method void org.kde.KWin.previousDesktop()
method Q_NOREPLY void org.kde.KWin.reconfigure()
method void org.kde.KWin.reconfigureEffect(QString name)
method void org.kde.KWin.refresh()
signal void org.kde.KWin.reinitCompositing()
signal void org.kde.KWin.reloadConfig()
method bool org.kde.KWin.setCurrentDesktop(int desktop)
method void org.kde.KWin.showWindowMenuAt(qlonglong winId, int x, int y)
method Q_NOREPLY void org.kde.KWin.toggleCompositing()
method void org.kde.KWin.toggleEffect(QString name)
method Q_NOREPLY void org.kde.KWin.unclutterDesktop()
method void org.kde.KWin.unloadEffect(QString name)
method bool org.kde.KWin.waitForCompositingSetup()
method QDBusVariant org.freedesktop.DBus.Properties.Get(QString interface_name, QString property_name)
method QVariantMap org.freedesktop.DBus.Properties.GetAll(QString interface_name)
method void org.freedesktop.DBus.Properties.Set(QString interface_name, QString property_name, QDBusVariant value)
method QString org.freedesktop.DBus.Introspectable.Introspect()

This is line noise to me.

August 06, 2010 @ 1:03 PM PDT
Cateogory: Linux
Tags: Hardware, KDE, Xorg

gaka 0.2.0

Per many commenters' suggestions and thanks to code from Steve Purcell, you can now use maps for CSS attributes in gaka.

user> (println (gaka/css [:a {:color :red}]))
a {
  color: red;}

This looks more like vanilla CSS thanks to the curlies, which is nice. You just have to keep in mind that your key/value pairs could end up being printed in random order, and order is significant1 in CSS.

It just so happens that maps are implemented in Clojure right now such that if they only have a few entries (16 key/value pairs), the order will be preserved, because you get a PersistentArrayMap instead of a PersistentHashMap. But it's highly dangerous to rely on such a thing. It could change at any time in the future.

In any case, you can also mix and match maps, lists and "flat" keyvals. They'll all be flattened That can help preserve attribute order in those cases where you need to.

user> (println (gaka/css [:a :color "red" {:padding 0} (list :margin 0)]))
a {
  color: red;
  padding: 0;
  margin: 0;}

I've also enhanced "mixins" a bit further. You can now mixin entire tags as well as attributes. Or a combination of both. Say you want a mixin that means "Make my element have no padding, and make links within the element be red":

user> (println (gaka/css [:div.foo mixin :margin 0]
                         [:div.bar mixin]))
div.foo {
  padding: 0;
  margin: 0;}

  div.foo a {
    color: red;}

div.bar {
  padding: 0;}

  div.bar a {
    color: red;}

You can get gaka from github or Clojars.

  1. Order is only significant in cases where you're doing things like padding: 0; padding-left: 1px. This is arguably bad CSS style, but it's valid, and it's also possible you'll have this kind of thing if you're generating CSS procedurally. But most of the time, order is not significant. e.g. it doesn't matter if you set text color first and background color second, or vice versa. So maybe this isn't so much of a problem in practice.

July 29, 2010 @ 1:59 PM PDT
Cateogory: Programming

Footnotes

Did you ever notice how footnotes make your writing seem more important1 somehow?

Maybe one reason is that "real" books use footnotes. At a glance, it looks like I have references2 backing up everything I say. In reality, I don't, but the connotation carries through somehow3. Now my blog seems scholarly and authoritative.

And if you're like me, you can't resist clicking footnotes to see what they refer to4. According to my estimates, by utilizing footnotes, in one fell swoop I have decreased my readers' average reading efficiency by 73%.

In any case, I've added experimental, rudimentary support for footnotes to cow-blog.

I'm loosely copying the syntax from Markdown Extra for this. Markdown is great, except when it isn't. The standard doesn't have support for some useful extensions. I use Showdown for Markdown support, and I'm probably going to work on adding more features of Markdown Extra to Showdown in the near future.

I just dread actually doing it. Showdown (like Markdown itself) is implemented as a series of hackish regex transformations of blobs of text. It's not a proper grammar. Implementing more of Markdown Extra means more regex blobbing. It's brittle and fragile and even getting incomplete support for footnotes was less than enjoyable. But at the same time I find myself wanting to do things that Markdown can't so, so I may have to bite the bullet.

(If there's a Showdown Extra out there already, drop me a URL. It'd be most appreciated. But I couldn't find one.)

  1. In reality nothing I say is important.

  2. Does my inner dialog count as a reference?

  3. Via telepathy.

  4. See?

July 27, 2010 @ 12:30 PM PDT
Cateogory: Programming

Review: Surely You're Joking, Mr. Feynman!

I'm probably the last person on earth to read "Surely You're Joking, Mr. Feynman!", a collection of stories and anecdotes from the life of Richard Feynman. But better late than never.

I'll keep this short. Feynman was the kind of nerd every nerd wishes he was, in one way or another. He was socially awkward. He was blunt and tactless. He felt out of place much of the time. And it was surprising to see how often Feynman expressed feelings of inadequacy. He wrote about being highly intimidated when talking in front of big names in physics, and jealous of the math abilities of some other people.

But none of that stopped him from having an exciting life. In fact he turned these traits to his advantage. He had romantic success, often via very highly unconventional means (e.g. walking up to girls and asking them for sex outright; they often said yes). His bluntness was seen as an admirable trait: where others might be intimidated by a famous physicist, Feynman would give his honest opinion, and that was often appreciated.

And Feynman went far outside his comfort zone. He did a stint in biology, even though he knew nothing of biology at the time. He went to Brazil and joined a samba band. He sold drawings and paintings for a while. He played drums for a ballet.

I picked up at least three lessons from this book.

  1. Try new things, even if you suck at them. Life is boring if you stick to what you're good at.

  2. Be intellectually honest. Brutally so. It's the only way to do good science, and arguably the only way to live a good life. I've always believed this, and Feynman hammers the point home well.

  3. Even the best and brightest of us feel insecure at times. You shouldn't let it stop you.

On top of all of that, reading of Feynman's time at Los Alamos working on The Bomb was a fascinating piece of history. I highly recommend this book.

And watch as much of Feynman on Youtube as you can find. It never ceases to be fascinating.

July 26, 2010 @ 4:19 PM PDT
Cateogory: Book Reviews

Review: Logitech Performance MX

I have a long list of companies I won't buy from, due to horrible customer service experiences or shoddy merchandise. On the other hand, my "Must buy from this company" list is awfully short.

Logitech is one company I'm generally OK buying from. (For now...) I go through computer mouses1 pretty fast, so I end up buying a new one every 4-5 years. Logitech hasn't failed me thus far.

In my opinion, the most important parts of your computer are the ones you interact with: Keyboard, mouse, monitor. I'd rather have a slow computer with a good mouse and keyboard than a fast computer with cheap peripherals. I already have a wonderful keyboard, and I like to have a nice mouse to match.

My latest mouse is the Logitech Performance MX.

Logitech Performance MX

July 26, 2010 @ 1:51 PM PDT
Cateogory: Hardware

Clojure syntax highlighting via SyntaxHighlighter

How do you syntax-highlight Clojure code for display on a website? The best way I can find is SyntaxHighlighter.

Daniel Gómez wrote a brush to give SyntaxHighlighter Clojure support. I tweaked it a bit myself and integrated it into cow-blog. I also converted my favorite color scheme to a SyntaxHighlighter theme. So when I write this code:

(defn- ip
  "Given a request, return the IP.  Looks for an x-forwarded-for
  header, falls back to :remote-addr on the request."
  [request]
  (or (get-in request [:headers "x-forwarded-for"])
      (request :remote-addr)))

You should see something like this:

Syntax highlighting example

...unless you're reading this via RSS, or in a browser without Javascript enabled, in which case you'll see plain, depressing black and white. But that's one nice thing about SyntaxHighlighter. It degrades nicely.

One bad thing about SyntaxHighlighter is that it doesn't play nicely with Markdown. Or rather, Markdown isn't powerful enough to let you specify the class of any markdown-generated HTML tags. If you want the <pre class="brush: clojure"> that SyntaxHighlighter requires, you have to write out the HTML by hand. But I hacked Showdown a bit to let me specify classes more easily, so I can avoid having to do that.

The code for all of this is on github with the rest of my blog.

July 21, 2010 @ 3:17 PM PDT
Cateogory: Programming