<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-970055329001593038</id><updated>2012-01-01T15:25:20.507-08:00</updated><category term='Python'/><category term='maxwell'/><category term='emacs'/><category term='git'/><category term='rdiff-snapshot-fs'/><category term='unix'/><category term='Zeya'/><category term='debian'/><category term='ssh'/><category term='PulseAudio'/><category term='Ubuntu'/><category term='bash'/><category term='Java'/><category term='Android'/><category term='regexps'/><category term='LaTeX'/><category term='amazing graphics papers'/><category term='computational research'/><category term='freerunner'/><title type='text'>I Still Know What You Learned Last Summer</title><subtitle type='html'>Life is too short for proprietary software</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://psung.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default?start-index=101&amp;max-results=100'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>158</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-290928709538492299</id><published>2011-09-17T02:42:00.000-07:00</published><updated>2011-09-17T02:43:28.789-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zeya'/><title type='text'>Zeya 0.6</title><content type='html'>&lt;p&gt;I'm pleased to announce the (long overdue&amp;hellip;) release
of &lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt; 0.6.&lt;/p&gt;
&lt;p&gt;This release contains only bug fixes and minor changes that help Zeya to "just work" under a wider variety of circumstances.&lt;/p&gt;
&lt;p&gt;Major changes since Zeya 0.5:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The 'dir' backend works with Python 2.5 again. (Thanks to Greg Grossmeier)&lt;/li&gt;
  &lt;li&gt;Broken symlinks are detected and ignored. (Thanks to Etienne Millon)&lt;/li&gt;
  &lt;li&gt;Unreadable playlist files are detected and ignored.&lt;/li&gt;
  &lt;li&gt;The 'dir' backend sorts files case-insensitively. (Thanks to Greg Grossmeier)&lt;/li&gt;
  &lt;li&gt;Zeya no longer leaks file handles under certain circumstances. (Thanks to Pior Bastida)&lt;/li&gt;
  &lt;li&gt;The frontend uses relative paths to resources, so Zeya can be run behind a reverse proxy out of the box, e.g. at &lt;tt&gt;http://yourhostname/path/to/zeya&lt;/tt&gt; (Thanks to Jérôme Charaoui)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;See &lt;a href="http://web.psung.name/zeya/"&gt;&lt;tt&gt;http://web.psung.name/zeya/&lt;/tt&gt;&lt;/a&gt; to learn more about Zeya, installation, getting started, reporting bugs, and development.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-290928709538492299?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/290928709538492299/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2011/09/zeya-06.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/290928709538492299'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/290928709538492299'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2011/09/zeya-06.html' title='Zeya 0.6'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4506120567943870808</id><published>2011-09-07T22:18:00.000-07:00</published><updated>2011-09-07T22:18:11.650-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PulseAudio'/><category scheme='http://www.blogger.com/atom/ns#' term='Zeya'/><title type='text'>Why Zeya?</title><content type='html'>&lt;p&gt;I noticed that &lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt; is now more
  than two years old. (Yow! Version 0.1 was released in August 2009! Thanks to
  you all for all the patches, by the way. Zeya has become much more popular
  than I would ever have guessed at the time.)&lt;/p&gt;

&lt;p&gt;This got me thinking about what has, and hasn't, gotten better in that time
  with respect to music software, and why I thought Zeya was so useful in the
  first place.&lt;/p&gt;

&lt;p&gt;Conceptually, you can think of any computer that is involved in playing your
  music as providing one or more of the following functions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Storage: storing your music in nonvolatile storage and retrieving it&lt;/li&gt;
  &lt;li&gt;Control: letting you push buttons and see what is playing or available to play&lt;/li&gt;
  &lt;li&gt;Playback: driving a set of speakers&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Traditionally all three functions have been performed by the same computer.
  But there's no reason they can't all run on different computers, not when you
  have a moderate- or high-speed network connecting them all. You might ask why
  you would actually want to separate these functions. The answer is that each
  function is best suited to be performed by a computer with a specific set of
  attributes, and the requirements for all of the functions are at odds with
  each other, and so require some compromise if they are to be colocated.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Storage wants to be done on a computer that has an enormous disk and is
    possibly continuously backed up.&lt;/li&gt;
  &lt;li&gt;Control wants to be done on a computer that is easy to reach
    (physically), possibly even one that fits in your pocket or can otherwise
    be carried around.&lt;/li&gt;
  &lt;li&gt;Playback wants to be done on a computer that permanently sits somewhere
    you want to hang out and is attached to a set of sweet speakers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The original impetus for writing Zeya was that it became clear to me that
  storage constraints were becoming increasingly annoying. People switched
  their portable devices from spinning rust (classic iPod and laptop HDDs) to
  flash memory (smartphones, smartphone-like devices like the iPod touch, and
  laptop SSDs), and all of a sudden, with the accompanying drop in capacity
  (most smartphones, for example, top out at just 16GB or 32GB), many people
  could no longer carry their entire music collection with them.&lt;/p&gt;

&lt;p&gt;At a higher level, Zeya completes the trio of tools that lets you decouple
  the components in varying ways:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Zeya and similar tools decouple storage from control and playback.
    Conceptually Amazon Cloud Player and Google Music are doing the same thing,
    too, though there the storage happens in the cloud.&lt;/li&gt;
  &lt;li&gt;X11 decouples control from storage and playback.&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2011/09/network-audio-with-pulseaudio-made.html"&gt;PulseAudio&lt;/a&gt;
    decouples playback from storage and control.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;(If you use any two of those, you can completely decouple all three
  functions, modulo the fact that X11 and PulseAudio don't work very well over
  high-latency links.)&lt;/p&gt;

&lt;p&gt;There has long been a patchwork of pieces that provide flexibility along one
  or more of the above dimensions (iTunes, Sonos, etc.) and have various
  tradeoffs; though, only in the past year have we seen the launches of
  high-profile products like Amazon Cloud Player and Google Music, which are
  more directly analogous to Zeya. All the attention in this area means that
  people are finally starting to understand the possibilities of the
  technology. Namely, that when you have network access everywhere, physical
  distance (and the need for the colocation of certain things) becomes much
  less important.&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4506120567943870808?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4506120567943870808/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2011/09/why-zeya.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4506120567943870808'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4506120567943870808'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2011/09/why-zeya.html' title='Why Zeya?'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2566631235153092683</id><published>2011-09-07T20:52:00.000-07:00</published><updated>2011-09-07T20:52:03.498-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PulseAudio'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Network audio with PulseAudio made (somewhat) easy</title><content type='html'>&lt;p&gt;I figured it was long past time to buckle down and learn how to make
  PulseAudio do my bidding and redirect audio across a network link. And I was
  surprised to learn that it's actually not hard to set up. In fact &lt;b&gt;you don't need to
  touch any config files in &lt;tt&gt;/etc&lt;/tt&gt;&lt;/b&gt;. Which you would never know, from
  reading most of the documentation that is out there.&lt;/p&gt;

&lt;p&gt;While network audio is still kind of flaky at times, you only "pay" for it
  if you use it (people complain about PulseAudio a lot, but in my experience
  it works very reliably when used locally), and it can come in very handy.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Background&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Throughout, I'll refer to the two computer roles as audio &lt;em&gt;source&lt;/em&gt;
  and audio &lt;em&gt;sink&lt;/em&gt; (where audio data is generated/decoded and where the
  speakers are attached, respectively). Note that these may differ from the
  PulseAudio concepts of the same names.&lt;/p&gt;

&lt;p&gt;Ubuntu ships with PulseAudio, and many apps (among the common graphical apps
  and music players) understand how to talk to PulseAudio now (possibly through
  a compatibility layer). Except maybe Flash, but everyone who uses Flash is
  already used to it not being a proper citizen. The default setup is to have a
  per-user instance of PulseAudio running alongside the X session. This means
  that someone has to be logged in to X on both ends. If your audio sink is
  headless then you might have a single system-wide PulseAudio instance
  instead. Configuring that is not covered here.&lt;/p&gt;

&lt;p&gt;PulseAudio runs as a service on port 4713. We need to first make that
  service discoverable on the machine with the audio sink, and then provide a
  way for the machine with the audio source to authenticate to the sink (so
  that you're not just letting &lt;em&gt;anyone&lt;/em&gt; on your network play their
  crappy music).&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Initial steps&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;On the machine with the audio sink:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Install and run &lt;tt&gt;paprefs &amp;&lt;/tt&gt;&lt;/li&gt;
  &lt;li&gt;Go to the &lt;b&gt;Network server&lt;/b&gt; tab.&lt;/li&gt;
  &lt;li&gt;Check &lt;b&gt;Enable network access to local sound devices&lt;/b&gt; and &lt;b&gt;Allow
      other machines on LAN to discover local sound devices&lt;/b&gt;. Autodiscovery
      uses Avahi, which you'll need to re-enable, if you ever disabled it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(You might have to restart PulseAudio or X for the settings to take
  effect.)&lt;/p&gt;

&lt;p&gt;I will describe two ways you can get the machine with the audio source to
  supply credentials to the sink so it can play music. The first one is likely
  to be more generally useful.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Using .pulse-cookie&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;The &lt;tt&gt;~/.pulse-cookie&lt;/tt&gt; file is a shared secret that can be used for
  authentication. Just copy that file from either machine (sink or source) to
  the other so that they are the same on both ends.&lt;/p&gt;

&lt;p&gt;At the audio source, install &lt;tt&gt;padevchooser&lt;/tt&gt; and run it
  (&lt;tt&gt;padevchooser &amp;&lt;/tt&gt;). A menu will appear in your notification area.
  Under &lt;b&gt;Default server&lt;/b&gt; you should see an entry for the sink, assuming it
  is on the same local network (it should be named &lt;tt&gt;username@hostname&lt;/tt&gt;).
  Select it.&lt;/p&gt;

&lt;p&gt;Now run the application of your choice and play some audio!&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Piggybacking on X11 forwarding&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;This method has the advantage of not requiring working autodiscovery. So you
  can use it on a LAN without Avahi running, or over a non-local network. All
  you need is to be able to SSH from the sink to the source. We will forward
  the audio from the source to the sink on a TCP port.&lt;/p&gt;

&lt;p&gt;For this method, we'll transfer the credentials that the source will need by
  writing them to the X11 &lt;em&gt;root window&lt;/em&gt;. PulseAudio supplies a program
  that does exactly this. On the machine with the audio sink, run:&lt;/p&gt;

&lt;blockquote&gt;&lt;tt&gt;sink$ start-pulseaudio-x11&lt;/tt&gt;&lt;/blockquote&gt;

&lt;p&gt;(You can double-check that this is working by running &lt;tt&gt;xprop -root | grep
    PULSE&lt;/tt&gt; and checking that there is an entry for &lt;tt&gt;PULSE_COOKIE&lt;/tt&gt;,
    among others.)&lt;/p&gt;

&lt;p&gt;Now initiate an SSH connection to the source, tunneling a port of your
  choice on that end over to your local PulseAudio server:&lt;/p&gt;

&lt;blockquote&gt;&lt;tt&gt;sink$ ssh -X -R &lt;b&gt;9998&lt;/b&gt;:localhost:4713 source&lt;/tt&gt;&lt;/blockquote&gt;

&lt;p&gt;Run the application of your choice and play some audio! As you are doing so,
  set the &lt;tt&gt;PULSE_SERVER&lt;/tt&gt; variable, which now enables your remote
  application to talk to your local audio hardware via the tunneled port.&lt;/p&gt;

&lt;blockquote&gt;&lt;tt&gt;source$ PULSE_SERVER=localhost:&lt;b&gt;9998&lt;/b&gt; rhythmbox &amp;&lt;/tt&gt;&lt;/blockquote&gt;

&lt;p&gt;&lt;b&gt;Conclusion and caveats&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Et voila&lt;/em&gt;, now you've decoupled your music player from your
  speakers. So you can play music from your laptop using the speakers at your
  desktop. Or you can play music from your desktop using the speakers in your
  living room. Some things to watch out for.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You may need to kill and restart &lt;tt&gt;pulseaudio&lt;/tt&gt; (or X) to get it to
    pick up some of those configuration changes.&lt;/li&gt;
  &lt;li&gt;PulseAudio will not move a stream while it is running, so if you use the
    menu to change the destination, the change will not take effect until the
    next song begins, unless you pause and restart playback in your audio
    application.&lt;/li&gt;
  &lt;li&gt;PulseAudio is kind of finicky and some of it still feels like black magic
    at times. You may need to restart it if you suddenly get errors about
    things not working, especially if they were just working a minute ago.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sources and further reading: &lt;a href="http://www.mail-archive.com/pulseaudio-discuss@mail.0pointer.de/msg09866.html"&gt;pulseaudio-discuss&lt;/a&gt;, &lt;a href="https://wiki.archlinux.org/index.php/PulseAudio"&gt;ArchLinux wiki&lt;/a&gt;, &lt;a href="http://ubuntuforums.org/showthread.php?p=11052460"&gt;Ubuntu forums&lt;/a&gt;&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2566631235153092683?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2566631235153092683/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2011/09/network-audio-with-pulseaudio-made.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2566631235153092683'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2566631235153092683'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2011/09/network-audio-with-pulseaudio-made.html' title='Network audio with PulseAudio made (somewhat) easy'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-3752475197682980318</id><published>2011-09-07T19:36:00.000-07:00</published><updated>2011-09-07T19:40:58.821-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LaTeX'/><title type='text'>QR codes in LaTeX</title><content type='html'>&lt;p&gt;If you are adding QR codes to print media, in order to make them look really
sharp, you want the QR codes to be generated in a vector format rather than a
bitmap format. It turns out that
the &lt;tt&gt;&lt;a href="http://ctan.org/tex-archive/graphics/pstricks/contrib/pst-barcode"&gt;pst-barcode&lt;/a&gt;&lt;/tt&gt;
package allows you to easily add vectorized QR codes to your LaTeX documents.&lt;/p&gt;

&lt;p&gt;Here are some minimal steps to generate a PDF with a QR code in it:&lt;/p&gt;

&lt;p&gt;1. Install dependencies:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$ aptitude install texlive-latex-{base,extra}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;(This works on Ubuntu 11.04, at least.)&lt;/p&gt;
&lt;p&gt;2. Add the following to a .tex file:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;\documentclass{article}
\usepackage{pst-barcode}
\usepackage{auto-pst-pdf}
\begin{document}
\begin{pspicture}(1in,1in)
  \psbarcode{&lt;b&gt;PAYLOAD&lt;/b&gt;}{eclevel=M width=1.0 height=1.0}{qrcode}
\end{pspicture}
\end{document}&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;where &lt;tt&gt;PAYLOAD&lt;/tt&gt; gives the data to be encoded. For a business card you
might have something like:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;MECARD:N:Sung,Phil;TEL:+14085551234;EMAIL:philbert@gmail.com;URL:http://web.psung.name;;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;See &lt;a href="http://code.google.com/p/zxing/wiki/BarcodeContents"&gt;this
    page&lt;/a&gt; for more &lt;tt&gt;MECARD&lt;/tt&gt; options and for descriptions of the other protocols (URLs, email addresses,
    etc.) that barcode readers understand.&lt;/p&gt;
&lt;p&gt;3. Compile your file as follows:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$ pdflatex &lt;b&gt;--shell-escape&lt;/b&gt; yourfile.tex&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Some notes:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;tt&gt;eclevel&lt;/tt&gt; specifies the level of error correction, and is one of
  &lt;tt&gt;L&lt;/tt&gt;, &lt;tt&gt;M&lt;/tt&gt;, &lt;tt&gt;Q&lt;/tt&gt;, &lt;tt&gt;H&lt;/tt&gt; (low to high)&lt;/li&gt;
  &lt;li&gt;&lt;tt&gt;width&lt;/tt&gt; and &lt;tt&gt;height&lt;/tt&gt; specify the dimensions of the
    barcode.&lt;/li&gt;
  &lt;li&gt;&lt;tt&gt;pst-barcode&lt;/tt&gt; knows how to generate barcodes in many other
  formats;
    see &lt;a href="http://mirrors.ctan.org/graphics/pstricks/contrib/pst-barcode/pst-barcode-doc.pdf"&gt;the
      documentation&lt;/a&gt; for details.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can also change the color of the barcode by adding something like the
following:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;b&gt;\usepackage{color}&lt;/b&gt;
[...]
  \psbarcode&lt;b&gt;[linecolor=blue]&lt;/b&gt;{PAYLOAD}[...]&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Sources: &lt;a href="http://tex.stackexchange.com/questions/10584/generating-2d-barcodes"&gt;StackExchange&lt;/a&gt;, &lt;a href="http://blog.widmann.org.uk/2009/05/27/1297/"&gt;Thomas Widmann&lt;/a&gt;, &lt;a href="http://bramp.net/blog/latex-qr-based-business-card"&gt;Andrew Brampton&lt;/a&gt; (who has a nice template for a business card)&lt;/p&gt;
&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-3752475197682980318?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/3752475197682980318/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2011/09/qr-codes-in-latex.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/3752475197682980318'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/3752475197682980318'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2011/09/qr-codes-in-latex.html' title='QR codes in LaTeX'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5995168050653066641</id><published>2011-08-08T01:07:00.000-07:00</published><updated>2011-08-08T01:07:38.931-07:00</updated><title type='text'>"X11 connection rejected because of wrong authentication."</title><content type='html'>&lt;p&gt;A brief note for posterity: if you are getting an error like the following,&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;X11 connection rejected because of wrong authentication.&lt;br&gt;xterm Xt error: Can't open display: localhost:10.0&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;one thing you might try, after you have eliminated &lt;a href="http://www.cyberciti.biz/faq/x11-connection-rejected-because-of-wrong-authentication/"&gt;the&lt;/a&gt; &lt;a href="http://jianmingli.com/wp/?p=724"&gt;usual&lt;/a&gt; &lt;a href="http://www.google.com/search?ie=UTF-8&amp;q=X11+connection+rejected+because+of+wrong+authentication."&gt;suspects&lt;/a&gt; (no, try those first, really), is unsetting the &lt;tt&gt;XAUTHORITY&lt;/tt&gt; environment variable:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;$ unset XAUTHORITY&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p style="text-align: center"&gt;* * *&lt;/p&gt;
&lt;p&gt;The remainder of this post is a followup to my previous
  post, &lt;a href="http://psung.blogspot.com/2008/10/stupid-screen-tricks.html"&gt;Stupid
  Screen Tricks&lt;/a&gt;. (The setup I described therein is still alive and well.)&lt;/p&gt;
&lt;p&gt;I received the above error when I started a screen session on
  display &lt;tt&gt;:0.0&lt;/tt&gt; and (after disconnecting and reconnecting) subsequently tried to launch, from within it, a new
  X program on a different display (even after setting &lt;tt&gt;DISPLAY&lt;/tt&gt;). The
  session inherits the old &lt;tt&gt;XAUTHORITY&lt;/tt&gt; value,
  which, for whatever reason, for as long as it is present, foils attempts to
  run programs on other displays.&lt;/p&gt;
&lt;p&gt;To work around this, I changed my &lt;tt&gt;here&lt;/tt&gt; utility alias to the
  following,&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;alias here='unset XAUTHORITY; DISPLAY=`cat ~/.last-display`'&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;that is, unsetting &lt;tt&gt;XAUTHORITY&lt;/tt&gt; as well as setting &lt;tt&gt;DISPLAY&lt;/tt&gt;
  before trying to run anything.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5995168050653066641?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5995168050653066641/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2011/08/x11-connection-rejected-because-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5995168050653066641'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5995168050653066641'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2011/08/x11-connection-rejected-because-of.html' title='&quot;X11 connection rejected because of wrong authentication.&quot;'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5249959720506583595</id><published>2011-08-08T00:35:00.000-07:00</published><updated>2011-08-08T00:35:45.010-07:00</updated><title type='text'>Assorted notes</title><content type='html'>&lt;ul&gt;&lt;li&gt;Hugin, the panorama-stitching tool, is quite slick these days (ever since it got some UI improvements in release 2010.4.0 or so, I believe). It handled perhaps 80-90% of the panoramas from &lt;a href="https://picasaweb.google.com/philbert/TourOfTheAlps2011"&gt;my recent trip&lt;/a&gt; in about 3 clicks and without manual intervention. Hats off to the Hugin developers.&lt;/li&gt;
&lt;li&gt;I've been learning how to twiddle the "Projection" knob in Hugin, which lets you change the geometry of the resulting panorama. For example, for photos of murals (or tapestries, or other long, flat, surfaces), the Rectlinear projection corrects for the distortion to reconstitute the "flat" image, as if you were standing far away.&lt;/li&gt;
&lt;/ul&gt;&lt;p style="text-align: center"&gt;&lt;img src="https://lh5.googleusercontent.com/-EfDB62_ujeI/Tj-NbSFQMwI/AAAAAAAAXNg/WyEyU1bs5K8/s640/4263b.jpg"&gt;&lt;br&gt;&lt;em&gt;Default (cylindrical)&lt;/em&gt;&lt;/p&gt;&lt;p style="text-align: center"&gt;&lt;img src="https://lh5.googleusercontent.com/-Dx_q0G8vMEI/Te5KLh_MRcI/AAAAAAAATYM/ZbuyO9vvawo/s640/4263.jpg"&gt;&lt;br&gt;&lt;em&gt;Corrected (rectilinear)&lt;/em&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Ubuntu has these new scrollbars with invisible scroll handles. They are quite annoying (being invisible and all). You can revert to the old ones like so:&lt;/p&gt;&lt;blockquote&gt;&lt;tt&gt;sudo apt-get remove overlay-scrollbar liboverlay-scrollbar-0.1-0&lt;/tt&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;a href="http://www.webupd8.org/2011/04/how-to-disable-overlay-scrollbars-in.html"&gt;Source&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5249959720506583595?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5249959720506583595/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2011/08/assorted-notes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5249959720506583595'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5249959720506583595'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2011/08/assorted-notes.html' title='Assorted notes'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='https://lh5.googleusercontent.com/-EfDB62_ujeI/Tj-NbSFQMwI/AAAAAAAAXNg/WyEyU1bs5K8/s72-c/4263b.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5127317212611551845</id><published>2011-06-17T16:24:00.000-07:00</published><updated>2011-06-17T16:24:08.678-07:00</updated><title type='text'>Spring cleaning, dealing with duplicate files, and vacuumpack</title><content type='html'>&lt;p&gt;I was doing some spring cleaning of my computer, part of which was removing
  duplicate files. I'm a packrat, and I subscribe to the
  copy-first-and-ask-questions-later school of thought, so I have a few
  duplicates floating around, just taking up disk space. (I think I have
  somewhere a filesystem copy of my previous computer, which, in turn, contains
  a filesystem copy of my computer before that.)&lt;/p&gt;

&lt;p&gt;There are plenty of tools that will help you remove duplicate files
  (&lt;a href="http://en.wikipedia.org/wiki/Fdupes"&gt;this page lists no fewer than
  16&lt;/a&gt;), but, disappointingly, none of them that I could find seem to give
  you a high-level understanding of where and how duplicate files appear in
  your filesystem. So I wrote &lt;tt&gt;&lt;b&gt;vacuumpack&lt;/b&gt;&lt;/tt&gt;, a short Python tool
  to help me really &lt;em&gt;see&lt;/em&gt; what was going on in my filesystem. Nothing
  revolutionary, but it helped me through my spring cleaning.&lt;/p&gt;

&lt;p&gt;(Aside 1: I noticed the parallel with coding theory: you want
    to &lt;a href="http://en.wikipedia.org/wiki/Data_compression"&gt;remove
    undesirable redundancy&lt;/a&gt;, by removing duplicate files on the same disk,
    and &lt;a href="http://en.wikipedia.org/wiki/Error-correction_code"&gt;add
    desirable redundancy&lt;/a&gt;, by using backups or RAID.)&lt;/p&gt;

&lt;p&gt;(Aside 2: This is simple enough that undoubtedly someone will send a pointer to a tool written circa 1988 that does what I am describing. C'est la vie; unfortunately it is usually easier, and more fun, to write code than to find it.)&lt;/p&gt;

&lt;p&gt;&lt;tt&gt;vacuumpack&lt;/tt&gt; is probably best explained by example.
  First, &lt;tt&gt;vacuumpack&lt;/tt&gt; can scan a directory and identify duplicated
  files:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;b&gt;$ ./vacuumpack.py --target=/home/phil --cache=/home/phil/.contentindex&lt;/b&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The output shows clusters of identical files. For example, &lt;em&gt;oh hey, it's
    the GPLv3&lt;/em&gt; (the cluster is prefaced by the &lt;tt&gt;sha256&lt;/tt&gt; of the
    shared content):&lt;/p&gt;

&lt;blockquote style="font-size: x-small"&gt;&lt;pre&gt;[...]
8ceb4b9ee5adedde47b31e975c1d90c73ad27b6b165a1dcd80c7c545eb65b903: 140588 bytes wasted
  /home/phil/projects/raytracer/COPYING (35147 bytes)
  /home/phil/projects/rdiff-snapshot-fs/source/COPYING (35147 bytes)
  /home/phil/projects/syzygy/COPYING (35147 bytes)
  /home/phil/projects/vacuumpack/COPYING (35147 bytes)
  /home/phil/source/emacs/COPYING (35147 bytes)
[...]&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;The clusters are sorted in decreasing order of the amount of space wasted,
  so you can fry the big fish first. Having multiple copies of the GPL floating
  around isn't really a cause for concern; let's have a look at another
  cluster:&lt;/p&gt;

&lt;blockquote style="font-size: x-small"&gt;&lt;pre&gt;6940e64dd91f1ac77c43f1f326f2416f4b54728ff47a529b190b7dadde78ea23: 714727 bytes wasted
  /home/phil/photos/20060508/may-031.jpg (714727 bytes)
  /home/phil/album1/c.jpg (714727 bytes)&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Thus far &lt;a href="http://duff.sourceforge.net/"&gt;&lt;tt&gt;duff&lt;/tt&gt;&lt;/a&gt; and many
  other tools do essentially the same thing. But most of the tools out there
  are focused on semi-mechanically helping you &lt;em&gt;delete&lt;/em&gt; files, even
  though cleaning up often requires &lt;em&gt;moving&lt;/em&gt; or &lt;em&gt;copying&lt;/em&gt; them as
  well.&lt;/p&gt;

&lt;p&gt;Duplicated photos, like the ones above, are probably something I want to
  resolve. Since I recall that &lt;tt&gt;/home/phil/photos&lt;/tt&gt; is the canonical
  location for most of my photos, the other directory looks somewhat suspect.
  So I'll ask &lt;tt&gt;vacuumpack&lt;/tt&gt; to tell me more about it:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;$ ./vacuumpack.py --target=/home/phil --cache=/home/phil/.contentindex &lt;b&gt;/home/phil/album1&lt;/b&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Now, for each file in that directory, &lt;tt&gt;vacuumpack&lt;/tt&gt; tells me whether
  it knows about any duplicates:&lt;/p&gt;

&lt;blockquote style="font-size: x-small"&gt;&lt;pre&gt;/home/phil/album1/a.jpg         == /home/phil/photos/20060508/may-010.jpg
/home/phil/album1/b.jpg         == /home/phil/photos/20060508/may-019.jpg
/home/phil/album1/c.jpg         == /home/phil/photos/20060508/may-031.jpg
/home/phil/album1/d.jpg         == /home/phil/photos/20060508/may-033.jpg
/home/phil/album1/e.jpg         == /home/phil/photos/20060508/may-048.jpg
/home/phil/album1/f.jpg         -- NO DUPLICATES
/home/phil/album1/g.jpg         == /home/phil/photos/20060508/may-077.jpg
/home/phil/album1/h.jpg         == /home/phil/photos/20060508/may-096.jpg&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;It looks like the files in &lt;tt&gt;/home/phil/album1&lt;/tt&gt; are a subset of the
  photos in &lt;tt&gt;/home/phil/photos&lt;/tt&gt;... except
  that &lt;tt&gt;/home/phil/photos&lt;/tt&gt; is missing a file! I need to copy that file
  back; once I do, the directory &lt;tt&gt;album1&lt;/tt&gt; is safe to delete.&lt;/p&gt;

&lt;p&gt;In this mode &lt;tt&gt;vacuumpack&lt;/tt&gt; is behaving like a directory diff tool,
  except that it uses content rather than filenames to match up files.&lt;/p&gt;

&lt;p&gt;A majority of the code in &lt;tt&gt;vacuumpack&lt;/tt&gt; is actually devoted to
  identifying duplicates efficiently. &lt;tt&gt;vacuumpack&lt;/tt&gt; stores the file
  hashes and metadata in a cache (specified by &lt;tt&gt;--cache=...&lt;/tt&gt;) and
  automatically rereads files when (and only when) they have been modified. So
  after the initial run, &lt;tt&gt;vacuumpack&lt;/tt&gt; runs very quickly (e.g. in just
  seconds on my entire homedir) while always producing up-to-date reports. It's
  fast enough that you can run it semi-interactively, using it to check your
  work continuously while you're reorganizing and cleaning your files. You can drill down and ask lots of questions about different directories without having to wait twenty minutes for each answer.&lt;/p&gt;

&lt;p&gt;I've posted a git repo containing the &lt;tt&gt;vacuumpack&lt;/tt&gt; source:&lt;/p&gt;

&lt;blockquote&gt;&lt;code&gt;git clone http://web.psung.name/git/vacuumpack.git&lt;/code&gt;&lt;/blockquote&gt;

&lt;p&gt;This has been tested on Ubuntu 11.04 under Python 2.7.1. You may use the
  code under the terms of the GNU GPL v3 or (at your option) any later
  version.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5127317212611551845?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5127317212611551845/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2011/06/spring-cleaning-dealing-with-duplicate.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5127317212611551845'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5127317212611551845'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2011/06/spring-cleaning-dealing-with-duplicate.html' title='Spring cleaning, dealing with duplicate files, and vacuumpack'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-739842112370207648</id><published>2011-06-17T14:38:00.000-07:00</published><updated>2011-06-17T14:38:14.702-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Assorted notes</title><content type='html'>&lt;ul&gt;
  &lt;li&gt;Public service announcement: earlier this year Google announced optional
    &lt;a href="http://www.google.com/support/accounts/bin/static.py?page=guide.cs&amp;guide=1056283"&gt;&lt;b&gt;2-factor
    authentication for Google accounts&lt;/b&gt;&lt;/a&gt;. &lt;em&gt;Please use it&lt;/em&gt;: it's
    one of the least painful ways to make your data safer (most people are
    toast if their email gets compromised). And the implementation seems fairly
    well thought out:&lt;/li&gt;
  &lt;ul&gt;
    &lt;li&gt;You download
      an &lt;a href="https://market.android.com/details?id=com.google.android.apps.authenticator"&gt;app&lt;/a&gt;
      to your smartphone (or smartphone-like device) that generates one-time
      passwords (OTPs), to be used in conjunction with your regular password
      when needed. A single OTP can authenticate one computer for up to 30
      days. Yes, the app is open source. It runs on any Android, Blackberry, or
      iOS device.&lt;/li&gt;
    &lt;li&gt;The app works offline, without a data connection, because the method
      for generating OTPs is specified
      by &lt;a href="http://tools.ietf.org/html/rfc4226"&gt;RFC 4226&lt;/a&gt; (yes, it's
      standardized and everything) and is either sequence-based or
      time-based.&lt;/li&gt;
    &lt;li&gt;Failing that, if you don't have a smartphone, or it's busted, you can
      also receive an OTP via SMS to a designated number (though, obviously,
      then you need phone reception).&lt;/li&gt;
    &lt;li&gt;Failing that, if you don't have a cell phone, or it's busted, you can
      also receive an OTP via a voice call to a designated landline.&lt;/li&gt;
    &lt;li&gt;Failing that... if you know you'll be somewhere where you have no phone
      at all, you can &lt;em&gt;print&lt;/em&gt; a list of OTPs to carry with you that will
      enable you to log in.&lt;/li&gt;
    &lt;li&gt;Apps that authenticate via just a password (e.g. the phone itself, or
      most desktop apps, like Picasa) get a dedicated automatically generated
      password. You don't get the benefit of 2-factor auth here, but these
      passwords are less likely to be phished because you're not typing them in
      all the time, and you can revoke them individually.&lt;/li&gt;
  &lt;/ul&gt;
  &lt;li&gt;Good lord, Ubuntu 11.04 (Natty) is fast. My laptop (Thinkpad X201 with
    Intel SSD) boots from disk unlock screen (LUKS full-disk encryption) to a
    working Openbox desktop in about &lt;em&gt;four seconds&lt;/em&gt;.&lt;/li&gt;
  &lt;li&gt;I've been playing
    with &lt;a href="http://www.blender.org/"&gt;&lt;b&gt;Blender&lt;/b&gt;&lt;/a&gt; (the Free 3D
    modeling tool) for a personal project to be 3D printed, and it's a lot of
    fun, and quite rewarding. I'm still a noob at this stuff, but already I get
    some of these "in the zone" moments that are so rarely attained in software
    (Emacs being the other exception) where I feel like I'm manipulating
    a &lt;em&gt;thing&lt;/em&gt; directly rather than &lt;em&gt;using a software program&lt;/em&gt;.
    The Blender UI looks like an airplane cockpit, but there is a method to
    its madness! The other neat thing is that most of the time when you do
    creative work on the computer you are not rewarded with anything nearly so
    tangible as a 3D printed piece.&lt;/li&gt;
  &lt;li&gt;A clever thing I noticed on Android the other week: when you use voice
    dictation in a text entry field, and you move the cursor back to previous
    words, above the keyboard it shows not the nearest alternatives based on the
    keyboard layout (as it would if you were typing), but the nearest alternatives
    based on sound&amp;mdash; e.g. "wreck" ... "a nice beach" as suggested
    replacements for "recognize speech".&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-739842112370207648?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/739842112370207648/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2011/06/assorted-notes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/739842112370207648'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/739842112370207648'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2011/06/assorted-notes.html' title='Assorted notes'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6464546265219629156</id><published>2011-02-27T23:11:00.000-08:00</published><updated>2011-02-27T23:11:00.618-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Reducing merge headaches: git meets diff3</title><content type='html'>&lt;p&gt;git has an option to display merge conflicts in &lt;tt&gt;diff3&lt;/tt&gt; format (by default it only displays the two files to be merged). You can
enable it like so:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;$ git config --global merge.conflictstyle diff3&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;Now, when you have to resolve merge conflicts, git shows your side, the side
being merged, and (here's what's new) the common ancestor in between them.
Here's an example of the &lt;tt&gt;diff3&lt;/tt&gt;-formatted output:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;cauliflower&lt;br&gt;
&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD&lt;br&gt;
peas&lt;br&gt;
potatoes&lt;br&gt;
||||||| merged common ancestors&lt;br&gt;
peas&lt;br&gt;
=======&lt;br&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; topic&lt;br&gt;
tomatoes&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;Having the merge ancestor readily available helps you to quickly determine
what the correct merge is, since you can infer from it the changes that were made on both sides. Here you can see that the original state
was &lt;tt&gt;peas&lt;/tt&gt;. On your branch &lt;tt&gt;potatoes&lt;/tt&gt; was added (compare the
middle section to the top) and on the other branch &lt;tt&gt;peas&lt;/tt&gt; was removed
(compare the middle section to the bottom). Therefore the correct change is to
both add &lt;tt&gt;potatoes&lt;/tt&gt; and remove &lt;tt&gt;peas&lt;/tt&gt;, leaving you with
just &lt;tt&gt;potatoes&lt;/tt&gt; in the conflicted section.&lt;/p&gt;
&lt;p&gt;There's really no reason you shouldn't enable the &lt;tt&gt;diff3&lt;/tt&gt;
style, because &lt;b&gt;you frequently need the ancestor to determine what the correct
merge is.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;To see that this is true, even in the simple example above, look at what the conflict looks like under the standard
style:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;cauliflower&lt;br&gt;
&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD&lt;br&gt;
peas&lt;br&gt;
potatoes&lt;br&gt;
=======&lt;br&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; topic&lt;br&gt;
tomatoes&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;There's an asymmetry between &lt;tt&gt;peas&lt;/tt&gt; and &lt;tt&gt;potatoes&lt;/tt&gt;: one was
added and one was deleted, but this merge conflict doesn't tell you anything at
all about which was which! You can't determine the correct merge unless you
remember the sequence of changes that led up to this point. And why should you
have to rack your brain to do that? That's exactly the sort of thing that your
computer can, and should, help you with.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Bonus tip: rerere (reuse recorded resolution)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;If your workflow finds you redoing the same merges over and over again you
might also find git's &lt;tt&gt;rerere&lt;/tt&gt; (reuse recorded resolution) feature to be
useful.&lt;/p&gt;
&lt;p&gt;One of the things that is wonderful about &lt;tt&gt;rerere&lt;/tt&gt; is that it
provides hardly any UI surface at all. Just set it...&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;$ git config --global rerere.enabled 1&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;...and forget it. Although there is a &lt;tt&gt;git rerere&lt;/tt&gt; command, you can get a lot done without using it at all.&lt;/p&gt;
&lt;p&gt;After enabling &lt;tt&gt;rerere&lt;/tt&gt;, whenever you resolve a merge conflict, git
automatically squirrels away the resolution in its database. You'll see a message like this
one:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;$ git commit&lt;br&gt;
Recorded resolution for 'soup'&lt;br&gt;
[...]&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;And the next time you encounter the same conflict, where you would have
expected git to spit out a file with conflict markers, you will instead find that it has automatically resolved the merge for you, and printed the
following message:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;$ git merge topic&lt;br&gt;
Auto-merging soup&lt;br&gt;
CONFLICT (content): Merge conflict in soup&lt;br&gt;
Resolved 'soup' using previous resolution.&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;Just double-check to make sure nothing has gone awry, add, and commit. Save
your blood, sweat, and tears for other, more interesting problems than redoing
merges.&lt;/p&gt;
&lt;p&gt;Further reading: &lt;a href="http://progit.org/2010/03/08/rerere.html"&gt;Pro Git on rerere&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6464546265219629156?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6464546265219629156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2011/02/reducing-merge-headaches-git-meets.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6464546265219629156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6464546265219629156'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2011/02/reducing-merge-headaches-git-meets.html' title='Reducing merge headaches: git meets diff3'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7472927547080272623</id><published>2011-01-25T20:11:00.000-08:00</published><updated>2011-01-25T20:11:19.337-08:00</updated><title type='text'>Making your own page-a-day calendar, revisited</title><content type='html'>&lt;p&gt;Some time ago I posted &lt;a href="http://psung.blogspot.com/2009/06/making-your-own-page-day-calendar.html"&gt;instructions for designing and producing a page-a-day calendar&lt;/a&gt;, which is a moderately neat project at the intersection of metaprogramming and handicraft.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.mattj.me/"&gt;Matt Johnson&lt;/a&gt; made one for the year 2011; &lt;a href="http://blog.mattj.me/latex-page-a-day-calendar" style="font-weight: bold"&gt;his write-up&lt;/a&gt; fills a lot of the gaps in my rather skeletal instructions and provides a number of suggestions for extending the original design in very good ways (including adding page content not based on photographs, and making a wooden stand for the calendar). Read it if you are thinking of making one of these things.&lt;/p&gt;
&lt;p&gt;Thanks, Matt!&lt;/p&gt;
&lt;p style="text-align: center"&gt;&lt;img src="http://lh6.ggpht.com/_egN-3IJO0Xg/TT-bKWE9okI/AAAAAAAAN_k/gu4rkIU2t4I/mattj1.jpg"&gt; &lt;img src="http://lh6.ggpht.com/_egN-3IJO0Xg/TT-bKdLVX5I/AAAAAAAAN_o/cm-79NzKKm8/mattj2.jpg"&gt;&lt;br&gt;&lt;small&gt;CC-BY &lt;a href="http://blog.mattj.me/"&gt;Matt Johnson&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://blog.mattj.me/latex-page-a-day-calendar" style="font-weight: bold"&gt;Read more.&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7472927547080272623?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7472927547080272623/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2011/01/making-your-own-page-day-calendar.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7472927547080272623'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7472927547080272623'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2011/01/making-your-own-page-day-calendar.html' title='Making your own page-a-day calendar, revisited'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_egN-3IJO0Xg/TT-bKWE9okI/AAAAAAAAN_k/gu4rkIU2t4I/s72-c/mattj1.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-1346743631853513496</id><published>2010-12-31T21:39:00.000-08:00</published><updated>2010-12-31T21:39:51.853-08:00</updated><title type='text'>2010 in Review</title><content type='html'>&lt;p&gt;These were the most linked-to posts on my blogs in the last year:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://philipsung.blogspot.com/2010/12/people-who-are-not-in-our-league-v.html"&gt;People Who Are Not In Our League V&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2010/10/thank-you-ubuntu.html"&gt;Thank You, Ubuntu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2007/12/for-else-in-python.html"&gt;for ... else in Python&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2010/04/thinkpad-trackpoint-scrolling-in-ubuntu.html"&gt;
      Thinkpad TrackPoint Scrolling in Ubuntu Lucid/10.04 (2010)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2008/09/scrolling-with-thinkpads-trackpoint-in.html"&gt;
      Scrolling with the Thinkpad's TrackPoint in Ubuntu (2008)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2009/12/subtleties-of-search-and-replace-in.html"&gt;Subtleties of search-and-replace in Emacs&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2009/09/getting-more-flow-from-your-window.html"&gt;Getting more "flow" from your window manager&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy new year, peace on earth, and may all your builds be green!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-1346743631853513496?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/1346743631853513496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/12/2010-in-review.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1346743631853513496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1346743631853513496'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/12/2010-in-review.html' title='2010 in Review'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6537625312946372513</id><published>2010-12-31T13:06:00.000-08:00</published><updated>2010-12-31T13:06:47.566-08:00</updated><title type='text'>Making the leap to SSD...</title><content type='html'>&lt;p&gt;The Intel SSDs were on sale around Thanksgiving, so I picked up one for my Thinkpad.&lt;/p&gt;

&lt;p&gt;There is little that was remarkable in getting it set up. I swapped out the
  old spinning rust device. (The X201, unlike any other laptop I've opened up,
  has rubber shock absorbers that fit between the drive and the chassis. Not
  that the thing they're guarding is particularly susceptible to mechanical
  damage any longer.) Everything just worked.&lt;/p&gt;

&lt;p&gt;Boot times and application load times are dramatically improved. Though, the
  way I work, my laptop is essentially just a device for running Emacs, Chrome,
  and gnome-terminal, all of which I just open and keep open. All of those apps
  load fairly quickly, so the speed improvement from the SSD, while nice, is
  not by any means life-changing. (And, how often do you reboot a computer,
  anyway? But, for the record, my Thinkpad goes from LUKS password prompt to
  login screen in 10 seconds, and to a ready-to-use desktop in about 3
  more.)&lt;/p&gt;

&lt;p&gt;What's really nice about the SSD is that my laptop is now nearly silent, or
  at least quieter than ambient noise. Perhaps I just have unusually low noise
  tolerance, but I find the steady-noise of a HDD to be somewhat annoying, and
  the sound of a HDD spinning up to be even more annoying. Unfortunately, I
  actually didn't correctly attribute those noises to the HDD until recently.
  If this sounds like you, it's time to pay a visit to the computer store.&lt;/p&gt;

&lt;p&gt;One caveat is that if you use LUKS full disk encryption (and if you're using a laptop, you really
  ought to; no, I mean, you &lt;em&gt;really&lt;/em&gt; ought to), then Ubuntu (10.10)
  doesn't issue TRIM commands to the device. Which will eventually lead to
  decreased throughput, but I believe that may just be the price of security. (IANA security expert...) LUKS goes
  to great lengths by default to foil cryptanalysis, including initializing
  encrypted partitions with random data to obscure which sectors of the device
  are actually being filled with interesting data. This would all be for naught
  if the OS was periodically telling the device exactly which sectors were no
  longer being used.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6537625312946372513?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6537625312946372513/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/12/making-leap-to-ssd.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6537625312946372513'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6537625312946372513'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/12/making-leap-to-ssd.html' title='Making the leap to SSD...'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6988177364595144824</id><published>2010-12-31T12:16:00.000-08:00</published><updated>2010-12-31T12:16:32.108-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='amazing graphics papers'/><title type='text'>Content-aware image resizing by seam carving</title><content type='html'>&lt;p&gt;This is a classic, or, as much of a classic as a 3-year-old graphics paper
  can be.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://yuwing.kaist.ac.kr/courses/CS770/reading/seamcarving.pdf"&gt;
  Seam Carving for Content-Aware Image Resizing&lt;/a&gt; (Avidan and Shamir, 2007)
  describes a technique for resizing photographs along one dimension in a way
  that allows the aspect ratio to be changed while reducing the amount of
  distortion in perceptually important parts of the image. Watch the video, if
  you haven't seen this before:&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;object width="480" height="385"&gt;&lt;param name="movie" value="http://www.youtube.com/v/qadw0BRKeMk?fs=1&amp;amp;hl=en_US"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/qadw0BRKeMk?fs=1&amp;amp;hl=en_US" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="480" height="385"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br&gt;&lt;a href="http://www.youtube.com/watch?v=qadw0BRKeMk"&gt;&lt;em&gt;Youtube link&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The algorithm translates into identifying the shortest path in a DAG and it
  can be easily implemented by a dynamic programming algorithm. As Dmitry
  pointed out to me some years ago, this makes an ideal teaching example for
  dynamic programming, for a number of reasons. The algorithm is easily
  visualized because the space of values to be computed maps straightforwardly onto the
  pixels of the image. Both the naive exponential-time algorithm (testing all
  3&lt;sup&gt;&lt;em&gt;#rows&lt;/em&gt;&lt;/sup&gt; paths) and the dynamic programming algorithm are
  fairly easily expressed without too much additional machinery. And, unlike most classroom dynamic programming
  questions I have encountered, which seemed either banal or contrived, the
  applications of this one are visually appealing and fairly interesting. For example, as someone
  pointed out to me, it makes the fallout of breaking up much easier to deal
  with.&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;img src="http://lh6.ggpht.com/_egN-3IJO0Xg/S2PnpccNTEI/AAAAAAAAD94/XQ9guBnwcPE/seamcarving.jpg"&gt;&lt;br&gt;Before... and after &lt;em&gt;(Source: video, above)&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6988177364595144824?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6988177364595144824/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/12/content-aware-image-resizing-by-seam.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6988177364595144824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6988177364595144824'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/12/content-aware-image-resizing-by-seam.html' title='Content-aware image resizing by seam carving'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_egN-3IJO0Xg/S2PnpccNTEI/AAAAAAAAD94/XQ9guBnwcPE/s72-c/seamcarving.jpg' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7730713713013010989</id><published>2010-12-31T11:47:00.000-08:00</published><updated>2010-12-31T11:47:59.343-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Some Android tips</title><content type='html'>&lt;p&gt;I've been using a Nexus One as my primary phone for about a year now. Here
  are some tips and suggestions I've accumulated. Most of these tips should
  also apply to the Nexus S and the G2 (which have stock Android builds), as
  well as to other Android phones (Froyo+) modulo any vendor
  customizations.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Press and hold the Search button to activate voice search / voice
     actions. This is indispensable! I use it a least a couple of times every
     day. It makes the phone feel like &lt;em&gt;future tech&lt;/em&gt;, not least because
     it's dramatically better than anything I regularly deal with in phone
     systems or on PCs. The phone recognizes special instructions, including
     things like the following (for anything it doesn't recognize as an action,
     it asks you to disambiguate or it falls back to a Google search):&lt;/li&gt;
  &lt;ul&gt;
    &lt;li&gt;"Call Phil Sung, mobile"&lt;/li&gt;
    &lt;li&gt;"Navigate to Fry's Electronics"&lt;/li&gt;
    &lt;li&gt;"Map of gas stations"&lt;/li&gt;
    &lt;li&gt;"Note to self, buy more envelopes" (which sends you an email from yourself)&lt;/li&gt;
  &lt;/ul&gt;
  &lt;li&gt;Press and hold the Home button to easily get a list of recently used
    apps.&lt;/li&gt;
  &lt;li&gt;Press and hold the Menu button to toggle the display of the soft
    keyboard. Not usually needed, but occasionally useful.&lt;/li&gt;
  &lt;li&gt;When using the soft keyboard, you can drag your finger past the top edge
    of the keyboard for quick access to digits and punctuation.&lt;/li&gt;
  &lt;li&gt;If you add your email address to the user dictionary, you can get it in
    the list of autocompletions when filling out forms in the web browser.&lt;/li&gt;
  &lt;li&gt;It's important to control the quantity of notifications so that they're
    at a level that is actually useful. Depending on how important some event
    is, you can configure the phone to make noise or merely to show you a
    notification the next time you turn on the phone. As an example, here's how
    I'm set up:&lt;/li&gt;
  &lt;ul&gt;
    &lt;li&gt;My phone only rings for phone calls, SMS, and IMs.&lt;/li&gt;
    &lt;li&gt;GMail generates a notification in the notification area but no noise
      (configurable in GMail settings). Even so, I implemented an elaborate
      system of GMail filters to keep all but the most important emails from
      getting to my inbox and thus generating notifications.&lt;/li&gt;
    &lt;li&gt;Calendar events generate neither noise nor notifications (configurable
      in Calendar settings). Instead, I put the Calendar widget on my home
      screen, and I just look at it whenever I need to. My calendar time is
      pretty sparsely scheduled, though. YMMV.&lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7730713713013010989?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7730713713013010989/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/12/some-android-tips.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7730713713013010989'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7730713713013010989'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/12/some-android-tips.html' title='Some Android tips'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7827218326281519553</id><published>2010-12-26T13:56:00.000-08:00</published><updated>2010-12-26T13:56:00.183-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Easy wifi autoconfiguration with barcodes</title><content type='html'>&lt;p&gt;ZXing's &lt;b&gt;Barcode Scanner&lt;/b&gt; Android app (the most popular barcode app for
  Android; it's available on the Market) can now configure a wifi network based
  on information encoded in a QR code.&lt;/p&gt;
&lt;p&gt;So you can say goodbye to having guests/patrons/visitors ask you how to log
  in to your wifi network every time someone new visits. Instead of having to
  select the correct network and type in the password (I thought computers were
  supposed to relieve us of this kind of drudgery), all they have to do is scan a
  barcode, and boom, they're online.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://zxing.appspot.com/generator/"&gt;&lt;b&gt;ZXing's QR Code
  Generator&lt;/b&gt;&lt;/a&gt; will help you make such a barcode (select "Wifi network" in
  the dropdown), after which you can just print it out and leave it in the living
  room.&lt;/p&gt;
&lt;p&gt;If you wish, you can also create such a barcode yourself just by encoding
  the SSID and password in the barcode payload. Here are a couple of examples
  that illustrate the encoding method:&lt;/p&gt;
&lt;table style="font-size: small; width: 100%"&gt;
  &lt;tr&gt;
    &lt;td style="text-align: center"&gt;
      &lt;p&gt;&lt;b&gt;WEP&lt;/b&gt;: &lt;tt&gt;WIFI:S:mynetwork;T:WEP;P:00deadbeef;;&lt;/tt&gt;&lt;/p&gt;
      &lt;p&gt;&lt;a href="http://chart.apis.google.com/chart?cht=qr&amp;chs=200x200&amp;chl=WIFI:S:mynetwork;T:WEP;P:00deadbeef;;"&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=qr&amp;chs=200x200&amp;chl=WIFI:S:mynetwork;T:WEP;P:00deadbeef;;"&gt;
   &lt;br&gt;(Example using Google Chart API)&lt;/a&gt;&lt;/p&gt;
    &lt;/td&gt;
    &lt;td style="text-align: center"&gt;
      &lt;p&gt;&lt;b&gt;WPA&lt;/b&gt;: &lt;tt&gt;WIFI:S:mynetwork;T:WPA;P:mypassword;;&lt;/tt&gt;&lt;/p&gt;
      &lt;p&gt;&lt;a href="http://chart.apis.google.com/chart?cht=qr&amp;chs=200x200&amp;chl=WIFI:S:mynetwork;T:WPA;P:mypassword;;"&gt;
   &lt;img src="http://chart.apis.google.com/chart?cht=qr&amp;chs=200x200&amp;chl=WIFI:S:mynetwork;T:WPA;P:mypassword;;"&gt;
   &lt;br&gt;(Example using Google Chart API)&lt;/a&gt;&lt;/p&gt;
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;Hat tip to &lt;a href="http://vikram.eggwall.com/"&gt;Vikram Aggarwal&lt;/a&gt; who
  implemented this concept, originally as a standalone app, &lt;a
  href="http://vikram.eggwall.com/computers/wyscan.html"&gt;WyScan&lt;/a&gt;, and then
  later implemented it in the Barcode Scanner app.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7827218326281519553?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7827218326281519553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/12/easy-wifi-autoconfiguration-with.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7827218326281519553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7827218326281519553'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/12/easy-wifi-autoconfiguration-with.html' title='Easy wifi autoconfiguration with barcodes'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-1427375012007159998</id><published>2010-12-22T21:55:00.000-08:00</published><updated>2010-12-22T21:55:25.593-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='bash'/><title type='text'>Inline expansion in bash</title><content type='html'>&lt;p&gt;&lt;tt&gt;bash&lt;/tt&gt; has a lot of shortcuts to save you typing and thinking
  time&amp;mdash; globs, shell aliases, and history expansion, for starters; and a
  bunch more.&lt;/p&gt;
&lt;p&gt;When you use &lt;tt&gt;bash&lt;/tt&gt; shortcuts extensively, though, you often end up
  with inputs that are rather, er, opaque, e.g.&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;$ !-3 -r [mnop]* !-3$&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;You have to be fairly brave to press ENTER without looking over that a few
  times. There is, though, a way out. Instead of trying to analyze what the
  hell it is you just wrote, you could just &lt;em&gt;ask the computer to tell you
  exactly what it's going to do&lt;/em&gt;. &lt;tt&gt;bash&lt;/tt&gt; has a number of features
  that facilitate this by expanding shortcuts for you to inspect before you
  execute them. I refer to these features collectively as &lt;strong&gt;inline
  expansion&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;There are three really useful inline expansion commands you can use at
  a &lt;tt&gt;bash&lt;/tt&gt; prompt that are essentially complementary to each other:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;History expansion&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;If you add the following to your &lt;tt&gt;.inputrc&lt;/tt&gt;,&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;$if Bash&lt;br&gt;
&amp;nbsp;&amp;nbsp;Space: magic-space&lt;br&gt;
$endif&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;then whenever you press space, any history expansions
  (e.g. &lt;tt&gt;!!&lt;/tt&gt;, &lt;tt&gt;!grep&lt;/tt&gt;, &lt;tt&gt;!-2&lt;/tt&gt;, &lt;tt&gt;!-3:1&lt;/tt&gt;, etc.) are
  expanded.&lt;/p&gt;
&lt;p&gt;You can also, at any time, press &lt;tt&gt;M-^&lt;/tt&gt; to perform history expansion
  (no configuration required). I prefer to set up magic space because you can
  just set it up and forget it about it, and subsequently you have one less
  thing to think about.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Glob expansion&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;&lt;b&gt;C-x *&lt;/b&gt;&lt;/tt&gt; expands the previous word into any filenames that match the
  glob. For example, &lt;tt&gt;/*&lt;/tt&gt; gets expanded into &lt;tt&gt;/bin /boot /cdrom /dev
  ...&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Shell expansion&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;&lt;b&gt;C-M-e&lt;/b&gt;&lt;/tt&gt; expands shell aliases, history, variables, commands, and
  arithmetic. For example:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;tt&gt;ls&lt;/tt&gt; into &lt;tt&gt;ls --color=auto&lt;/tt&gt; (based on any &lt;tt&gt;alias&lt;/tt&gt; directives you have)&lt;/li&gt;
  &lt;li&gt;&lt;tt&gt;!grep&lt;/tt&gt; into &lt;tt&gt;grep 2010 mylogfiles&lt;/tt&gt; (based on your history)&lt;/li&gt;
  &lt;li&gt;&lt;tt&gt;$DISPLAY&lt;/tt&gt; into &lt;tt&gt;:0.0&lt;/tt&gt;&lt;/li&gt;
  &lt;li&gt;&lt;tt&gt;`whoami`&lt;/tt&gt; into &lt;tt&gt;phil&lt;/tt&gt;&lt;/li&gt;
  &lt;li&gt;&lt;tt&gt;$((3+5))&lt;/tt&gt; into &lt;tt&gt;8&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: center"&gt;* * * * *&lt;/p&gt;
&lt;p&gt;I find these features useful for the same reason I
  use &lt;a href="http://psung.blogspot.com/2010/08/gnu-parallel.html"&gt;GNU
  Parallel&lt;/a&gt; the way I do: they really improve the &lt;em&gt;interactivity&lt;/em&gt; of
  my work&amp;mdash; in the sense that I get much faster empirical feedback on whether
  I'm doing a complex task correctly (the computer tells &lt;em&gt;me&lt;/em&gt; what it
  thinks I'm trying to say), rather than me having to reason (unreliably) about
  what I wrote and recall a bunch of history and read the man page for the
  umpteenth time because I'm second-guessing myself.&lt;/p&gt;
&lt;p&gt;Inline expansion is useful in a different scenario as well, namely, once
  you expand a glob or a shell alias you're free to (interactively) make
  changes to it. For example, if you want to delete all the files but one in a
  directory, start with &lt;tt&gt;rm *&lt;/tt&gt;, press &lt;tt&gt;C-x *&lt;/tt&gt; (which expands the glob into a list of all the files in the current directory), and edit out the
  name of the file you want to keep. Or if you want to run one of your
  shell-aliased commands, but without one of the flags, expand it
  with &lt;tt&gt;C-M-e&lt;/tt&gt; and then edit it.&lt;/p&gt;
&lt;p&gt;Further reading:
  &lt;a href="http://www.ukuug.org/events/linux2003/papers/bash_tips/"&gt;A nice &lt;tt&gt;bash&lt;/tt&gt; tips slide deck by Simon Myers&lt;/a&gt;;
  &lt;a href="http://www.gnu.org/software/bash/manual/html_node/Miscellaneous-Commands.html"&gt;"Miscellaneous [Readline] Commands"
    in the &lt;tt&gt;bash&lt;/tt&gt; manual&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-1427375012007159998?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/1427375012007159998/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/12/inline-expansion-in-bash.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1427375012007159998'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1427375012007159998'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/12/inline-expansion-in-bash.html' title='Inline expansion in bash'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7517101496839605077</id><published>2010-10-21T08:15:00.000-07:00</published><updated>2010-10-21T11:31:43.135-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Usability gems in GNU/Linux</title><content type='html'>&lt;p&gt;My post
  &lt;a href="http://psung.blogspot.com/2010/10/thank-you-ubuntu.html"&gt;Thank you,
    Ubuntu&lt;/a&gt; attracted some attention (hello, Hacker News!). A couple of
    commenters were skeptical of my assertion that GNU/Linux is more usable
    than the major proprietary operating systems&amp;mdash; and rightly so, since I
    didn't really elaborate on it at the time. For example, commenter Dubc wrote:&lt;/p&gt;

&lt;blockquote&gt;&lt;p&gt;&lt;em&gt;I think Ubuntu is a fine choice indeed, but you are going to either have to use another word than usability, or redefine the term to meet your presumptions.&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;

&lt;p&gt;So I'd like to expand on a few
    of the things that make Ubuntu such a pleasure to use, for those who aren't
    familiar with its ins and outs, especially because I so rarely see people
    take the time to articulate some of these nifty constructs at a high
    level.&lt;/p&gt;

&lt;p&gt;I will happily grant that at the application level, Windows and Mac OS have
  a much more consistent base of polished applications. And Apple has an
  attention to detail and psychology that others would do well to learn
  from.&lt;/p&gt;

&lt;p&gt;It's often said that Apple takes the time to get the little things right.
  Unfortunately, at times I think they should have instead spent a bit more
  time thinking through the &lt;em&gt;big&lt;/em&gt; things in Mac OS. There are some
  fairly glaring architectural/design/HCI problems on the Mac (and on Windows,
  too) that hamper users needlessly. And because these are issues with how one
  interacts with the system at its most basic levels, no amount of polish on
  the "little things" can really satisfactorily outweigh them.&lt;/p&gt;

&lt;p&gt;What that boils down to is this: yes, you will wrestle with GNU/Linux for a
  few hours or days or weeks when you get it set up. But if you use Windows or
  Mac OS, you will wrestle with it every minute of every day you're using it.
  Forever. And that's just not what "usability" means to me.&lt;/p&gt;

&lt;p&gt;Here are some illustrative examples:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;apt&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;An anonymous commenter wrote:&lt;/p&gt;

&lt;blockquote&gt;&lt;em&gt;in Mac installing software is a single drag-and-drop
    function&lt;/em&gt;&lt;/blockquote&gt;

&lt;p&gt;Oh, if only that were the case. The flow for installing software on
  Windows/Mac looks something like this (some steps omitted for brevity):&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open a web browser and search for the software you want.&lt;/li&gt;
  &lt;li&gt;Navigate to the vendor's web page, fish around for the download link, and
    start downloading the software. Wait.&lt;/li&gt;
  &lt;li&gt;Find the file you downloaded and open the installer/archive.&lt;/li&gt;
  &lt;li&gt;Accept the license agreement.&lt;/li&gt;
  &lt;li&gt;Drag the item to the dock (Mac only).&lt;/li&gt;
  &lt;li&gt;Answer some setup questions. Wait.&lt;/li&gt;
  &lt;li&gt;Delete the installer/archive.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These steps are error-prone, and unsophisticated users will quickly find
  themselves with malware on their systems. We should help users to do the
  right thing by default when installing software, and subjecting them to the
  vagaries of the wide-open web isn't the right thing.&lt;/p&gt;

&lt;p&gt;On Ubuntu:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Open Synaptic and search for the software you want.&lt;/li&gt;
  &lt;li&gt;Click install. Wait.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Whatever the heck you want, you can find it in Synaptic. And there's no
  distinction between software that was preinstalled with your system and
  software that you choose to install later. It all works the same way and gets
  security updates in the same way. And it looks like Mac OS is finally
  starting to head in this direction with the App Store for Mac software.&lt;/p&gt;

&lt;p&gt;But, what's more, each of the thousands of pieces of software available in
  the Ubuntu (or whatever distro you use) repository has an audit trail, and&amp;mdash; unlike the apps you get in the Mac App Store, or any "App Store," really&amp;mdash;
  Ubuntu has the means, motive, and opportunity to do whatever it takes to make
  them "just
  work," no matter where and when and for whom it was originally written. There
  is a vast body of software that is just considered to be &lt;em&gt;part of your
  operating system&lt;/em&gt; and is maintained alongside it, and Ubuntu will vouch
  for that software just as it will vouch for the software at the core of your system.&lt;/p&gt;

&lt;p&gt;It's not clear whether you will ever see that sort of large-scale
  integration work in a proprietary OS. Package management is really one of the
  highlights of the free software ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Remote access&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;X11 has pretty much decoupled &lt;em&gt;where a program runs&lt;/em&gt; and &lt;em&gt;where
  the program can be used&lt;/em&gt;. You have a few basic composable tools&amp;mdash;
  SSH, X forwarding, and port forwarding&amp;mdash; and all of a sudden the vast
  majority of applications can be invoked remotely. So you can, very easily,
  interact with a program that's using the resources (CPU, filesystem, network
  bandwidth) of a computer sitting somewhere else. There are a few gotchas with
  respect to X11 (watch out for high-latency network links, for example), but
  by and large it works.&lt;/p&gt;

&lt;p&gt;"But wait," you say, "Mac OS has SSH and X11 too." Except that most of the
  apps you want to use can't be invoked remotely, because they aren't X11 apps.
  So you have a litany of tricks. VNC and NX are appropriate sometimes, but they're
  clunky. Mac OS has "Back to My Mac" which is a slightly more general tool
  (and costs $99/year). But typically, whenever you work remotely you have to
  work differently too. It's
  a far cry from the situation on GNU/Linux, where you have a critical mass of
  applications you can use remotely and they just work, more or less
  transparently.&lt;/p&gt;

&lt;p&gt;The result is that Mac and Windows users are typically &lt;em&gt;highly dependent
    on a single piece of hardware&lt;/em&gt;. If you have a nice light laptop, more
  power to you. They say the best computer is the one you always have with
  you, after all. But even better than that is not having to carry a computer
  around. It's incredibly liberating, not to mention convenient. You can
  actually go places without having to pack a bag.&lt;/p&gt;

&lt;p&gt;On GNU/Linux, one barely even perceives the &lt;em&gt;concept&lt;/em&gt; of "other
  computers." Every computer you use, no matter how far away it is, is so
  accessible to you, so immediate, that it might as well &lt;em&gt;be&lt;/em&gt; the one
  sitting on your lap right now.&lt;/p&gt;

&lt;p&gt;Of course, Microsoft and Apple don't really have any incentive to make
  remote access terribly effective. Since they generally sell you a license to
  use a particular instance of their software on a particular computer, it
  would cut into their bottom line to make remote access actually useful. So
  they won't.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Window managers&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;The Windows/Mac window managers (the part of your OS that lets you
  manipulate windows and switch between them) are pretty bad. They weren't
  always this way&amp;mdash; they have become noticeably clunkier on the large
  displays that are so common today.&lt;/p&gt;

&lt;p&gt;On large displays, maximizing (zooming) windows is not useful much of the
  time. Maximized windows are just too big. Instead you have to move and resize
  windows to obtain a useful multi-window arrangement on your screen. But
  Windows and Mac OS give you very little help in this regard. To produce these
  arrangements you usually have to click on some tiny button/target and
  manually move windows around.&lt;/p&gt;

&lt;p&gt;For example, moving or resizing windows on Windows or Mac OS typically
  requires you to point at the titlebar or resize handle or window
  border&amp;mdash; both of which are just a few pixels wide.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Fitts's_law"&gt;Fitts's Law&lt;/a&gt;?
  Bueller? &lt;em&gt;Bueller&lt;/em&gt;? Having enabled alt-dragging to move or resize on
  any capable X window manager (I
  use &lt;a href="http://openbox.org/wiki/Main_Page"&gt;Openbox&lt;/a&gt;, but even the Ubuntu default window manager supports this), the entire
  window becomes your drag target. The &lt;em&gt;entire window&lt;/em&gt;. (Alternatively,
  if you use a tiling window manager, even the whole concept of manually moving
  windows around becomes basically moot.)&lt;/p&gt;

&lt;p&gt;In fairness to Apple and Microsoft, they have taken some steps in the right
  direction recently. Windows 7 "docks" windows to one side of the screen when
  you ask it to. You can configure some recent Macs to let you drag windows
  with three fingers (or so I've heard). And Mac recently gained Spaces (i.e.
  virtual desktops) too.&lt;/p&gt;

&lt;p&gt;Unfortunately, I think these are the exceptions that prove the rule. Mac OS
  and Windows users have waited for years only to get a fraction of the window
  management facilities that you could have set up in your X11 window manager.
  Supposing you spent an hour setting up your WM to your liking, I figure you would earn
  back that time in improved productivity in just a few weeks, rather than having to wait years for Microsoft or Apple to implement a sensible workflow. But more
  importantly, your blood pressure would go down, immediately.&lt;/p&gt;

&lt;p&gt;People really are more effective when they can set up their computers to work they
  way they want. But on Windows and Mac OS they aren't given the tools they need to do
  so. I wouldn't disparage these operating systems so much if they came with
  window managers that could at least be configured to be minimally adequate.
  But they don't.&lt;/p&gt;

&lt;p&gt;The window manager is the one program you're using all the time, even when
  you're using other programs. It's your primary vehicle for multitasking and
  your command center for managing your work on a second-by-second basis. So it's really important to get this right.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;p&gt;

&lt;p&gt;Having read this post, you might decide that you would brand these issues
  not as "usability" issues but as something else. Which is completely fine by
  me. A rose by any other name, after all&amp;hellip;&lt;/p&gt;

&lt;p&gt;Many of the cumbersome rituals that Windows and Mac OS have whittled away at
  over the years are completely unnecessary in Ubuntu. And this is why, while
  I've had occasion to use a Mac (at various times since 2004 or so) and
  Windows (only occasionally), sitting down at one always feels like death by a
  thousand cuts. They're superficially simpler, but really quite tiresome once
  you get beneath the surface. It seems that hey are optimized
  for learnability at the expense of usability. That is is exactly the wrong
  optimization to make, if you use a computer for a living.&lt;/p&gt;

&lt;p&gt;Life is just too short for that.&lt;/p&gt;

&lt;p&gt;Now, it's not like Ubuntu is a paragon of usability out of the box, either, though some of the things I mention above do just work by default.
  The difference&amp;mdash; the key difference&amp;mdash; is that you can make it
  into one without much hassle.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7517101496839605077?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7517101496839605077/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/10/usability-gems-in-gnulinux.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7517101496839605077'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7517101496839605077'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/10/usability-gems-in-gnulinux.html' title='Usability gems in GNU/Linux'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6207428312803441060</id><published>2010-10-20T19:10:00.000-07:00</published><updated>2010-10-20T19:10:00.227-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Android'/><title type='text'>Instant messaging on Android</title><content type='html'>&lt;p&gt;I've been using a Nexus One as my primary phone for the last few months now,
  and I quite like it! Upon reflection, the thing I most like about it,
  however, is not something I had anticipated at all when I got the phone.&lt;/p&gt;

&lt;p&gt;Being able to search the web, read email, run apps, look at maps, and listen
  to podcasts are all very convenient. Though, there is not much to say
  about those things: I use those tools in more or less the same way I would use them
  if I had a laptop with me.&lt;/p&gt;

&lt;p&gt;However, being able to send and receive IMs from my phone has been one of a
  small number of applications that has led to a qualitative change in the way I
  do things. I'm using IM a lot more now, at the expense of pretty much every other form of communication. And that's because &lt;b&gt;instant messaging is the only mode of
  communication that actually feels convenient&lt;/b&gt;.&lt;/p&gt;

&lt;p&gt;You can write and reply whenever you want, not just when it's convenient for
  the other person (unlike phone calls). You can have rapid back-and-forth
  conversations (unlike e-mail and voice mail). You can write messages of
  whatever length you want (unlike SMS). You can communicate unobtrusively,
  e.g. in a library (unlike phone calls and voice mail). You can read messages
  without going through an absurd interface (unlike voice mail). Your messages
  reach you on whatever device you're using&amp;mdash; desktop, laptop, or phone
  (unlike phone calls and SMS). It doesn't cost an exorbitant amount of money
  (unlike SMS). (As for video calling, it has pretty much all the disadvantages and restrictions of voice calls, plus some more. It's a cool tech demo, but not something I expect to use on a day-to-day basis.)&lt;/p&gt;

&lt;p&gt;If you think about where and when and how you can use each mode of communication, IM matches or surpasses pretty much everything else on most axes. Sometimes you need the phone or email for a high-bandwidth conversation or to deliver a large payload. But those occasions are getting to be few and far between.&lt;/p&gt;

&lt;p&gt;Part of it is just the medium&amp;mdash; &lt;em&gt;IM is as synchronous or as asynchronous
  as you want it to be&lt;/em&gt;&amp;mdash; but a good part of the goodness here is thanks to
  Android's implementation. You can dictate messages with your
  voice; for short common messages (e.g. "call me when you get home") it
  works quite well, so you can dash off quick messages using whatever modality is more convenient, keyboard or voice. And the Android notification system notifies you of new
  messages and lets you bring up conversations easily&amp;mdash; but discreetly, without interrupting whatever else you are doing on the
  phone.&lt;/p&gt;

&lt;p&gt;For me, IM is the killer app for carrying a smartphone in my pocket, ranking significantly above "browsing the web" and a fair amount above "making phone calls".&lt;/p&gt;
&lt;p&gt;(Incidentally, the words "phone" and "smartphone" seem so inadequate after you have come to fathom this super-communications capability you have on your hands.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6207428312803441060?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6207428312803441060/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/10/instant-messaging-on-android.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6207428312803441060'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6207428312803441060'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/10/instant-messaging-on-android.html' title='Instant messaging on Android'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-3924789528485843515</id><published>2010-10-05T23:40:00.000-07:00</published><updated>2010-10-05T23:40:22.469-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zeya'/><title type='text'>Zeya 0.5</title><content type='html'>&lt;p&gt;I'm pleased to announce the release of &lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt; 0.5 (also&amp;mdash; Hello, &lt;a href="http://www.reddit.com/r/linux/comments/djcdk/zeya_music_server_with_html5_interface/"&gt;Reddit&lt;/a&gt;!).&lt;/p&gt;

&lt;p style="text-align: center"&gt;&lt;img src="http://web.psung.name/zeya/images/zeya5-small.png"&gt;&lt;/p&gt;

&lt;p&gt;Major changes since Zeya 0.4:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Playlist support. The 'rhythmbox' and 'dir' backends detect playlists
  you've saved (in Rhythmbox or as M3U/PLS files, respectively) and let you choose from among them (using the dropdown in the upper left corner).&lt;/li&gt;
&lt;li&gt;PLS format playlists are now supported by the 'playlist' backend. The format of the playlist (M3U or PLS) is guessed automatically based on the extension. (Amit Saha)&lt;/li&gt;
&lt;li&gt;Support for decoding m4a files. (Rainer Hahnekamp)&lt;/li&gt;
&lt;li&gt;Bind Zeya to a single interface only with the new &lt;tt&gt;--bind_address&lt;/tt&gt;
  flag. See the &lt;a href="http://web.psung.name/zeya/cookbook/"&gt;cookbook&lt;/a&gt;
  for more info. (Bj&amp;ouml;rn Lohrmann)&lt;/li&gt;
&lt;li&gt;More UI.&lt;/li&gt;
&lt;li&gt;Bug fixes. Zeya now "just works" under a wider variety of circumstances. (Samson Yeung and others)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Known issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The 'dir' backend doesn't work with Python 2.5. A fix has been checked in at git HEAD.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See &lt;a href="http://web.psung.name/zeya/"&gt;&lt;tt&gt;http://web.psung.name/zeya/&lt;/tt&gt;&lt;/a&gt; for more information about Zeya, installation, getting started, and reporting bugs.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-3924789528485843515?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/3924789528485843515/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/10/zeya-05.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/3924789528485843515'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/3924789528485843515'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/10/zeya-05.html' title='Zeya 0.5'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-408733768037730650</id><published>2010-10-01T22:02:00.000-07:00</published><updated>2010-10-01T22:02:00.367-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Thank you, Ubuntu</title><content type='html'>&lt;p&gt;Ubuntu 10.10, the Maverick Meerkat, will be released in just a couple of
  weeks. That got me reflecting on the fact that I have been a happy user of
  Ubuntu for what must be over 5 years now. That's a long time!&lt;/p&gt;

&lt;p&gt;The GNU/Linux variants are the only OSes I've used where I really have the
  flexibility to define my own workflow (&lt;a
  href="http://psung.blogspot.com/2009/09/getting-more-flow-from-your-window.html"&gt;example&lt;/a&gt;).
  So they are a pleasure to use (ok, &lt;em&gt;most&lt;/em&gt; of the time). I use a computer
  for many, many hours a day nearly every day. And the time spent customizing
  software and learning it is a drop in the bucket when it's amortized over the
  months and years I'm going to spend using it. Sure, Windows and Mac OS are a
  bit more learnable and easier to get started with&amp;mdash; but they are much
  less &lt;em&gt;usable&lt;/em&gt;. And for me, and most other people who sit at a computer
  for a living, that is precisely the wrong optimization to make.&lt;/p&gt;

&lt;p&gt;There's plenty more to love about Ubuntu: for starters, that it runs on
  every piece of hardware you throw at it; how with &lt;a
  href="http://psung.blogspot.com/2008/06/managing-dotfiles-with-git-continued.html"&gt;a
  modest amount of effort&lt;/a&gt;, you can make all the computers you use behave
  exactly the same; and how great &lt;tt&gt;apt&lt;/tt&gt; is (really, it takes the fear
  and hassle out of installing software, and it's an experience that no
  proprietary desktop OS comes close to).&lt;/p&gt;

&lt;p&gt;Ubuntu is far from perfect, but it is pretty marvelous, and all the
  GNU/Linux operating systems have come a long way in the last 5 years. When I
  step back, I'm a bit astonished that Ubuntu or anything
  like it even exists at all. It works, it's powerful, it's free of charge,
  and, with small carve-outs, all of it is free for &lt;em&gt;anyone&lt;/em&gt; to do
  &lt;em&gt;anything&lt;/em&gt; they wish with it.&lt;/p&gt;

&lt;p&gt;One thing I rarely stop thinking about is how technology can be made to be
  an instrument of empowerment. And I believe that one necessary step in that
  direction is ensuring that you are the master of all these amazing devices
  you carry around with you all the time: that they serve you and carry out
  your will, and not the other way around. Ubuntu has this vast collection of
  software you can use as the substrate for doing &lt;em&gt;anything&lt;/em&gt;, and the
  question isn't "&lt;em&gt;Will the creators of this software give you permission to
  do this?&lt;/em&gt;" but rather "&lt;em&gt;Who the hell is going to stop you?&lt;/em&gt;".&lt;/p&gt;

&lt;p&gt;I find this an incredibly heartening idea, almost a cousin of the concept of
  Turing's &lt;em&gt;universal machine&lt;/em&gt;&amp;mdash; the possibility, realizable in
  software, that you are limited by nothing other than your imagination.
  Unfettered computation is really a magical thing. And Ubuntu is a wonderful
  demonstration of that assertion, though by no means the only one.&lt;/p&gt;

&lt;p&gt;So, to everyone that helped to make this possible (Canonical; the Ubuntu
  community; Debian developers; kernel developers; upstream maintainers and
  contributors of all stripes; and yes, even the folks working on other
  downstreams, like RH/Fedora&amp;mdash; your code makes its way into Ubuntu
  too):&lt;/p&gt;

&lt;p&gt;You have truly helped to make something wonderful, and it's a real gift to
  humanity. Thank you.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-408733768037730650?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/408733768037730650/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/10/thank-you-ubuntu.html#comment-form' title='17 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/408733768037730650'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/408733768037730650'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/10/thank-you-ubuntu.html' title='Thank you, Ubuntu'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>17</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-1027026198452330753</id><published>2010-09-29T22:49:00.000-07:00</published><updated>2010-10-25T11:09:31.443-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Java'/><title type='text'>Guava</title><content type='html'>&lt;p&gt;A public service announcement for Java programmers.&lt;/p&gt;
&lt;p&gt;Google has released as Free software a bunch of convenience libraries used
  internally in Google Java code. The project is (very cleverly) called
  &lt;a href="http://code.google.com/p/guava-libraries/"&gt;Guava&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The libraries span a huge range of functionality, but I think that in
  general they help to promote a more functional programming style and they
  paper over some of Java's warts.&lt;/p&gt;
&lt;p&gt;Here are three of my favorite things from Guava, but if you &lt;a
  href="http://guava-libraries.googlecode.com/svn/trunk/javadoc/index.html"&gt;read
  the Javadocs&lt;/a&gt; you will undoubtedly find more cool stuff. Looking at all of
  this, you might decide that it's all simple stuff that you could implement
  yourself in about five minutes. Of course you could (in &lt;em&gt;some cases&lt;/em&gt;,
  anyway), but why would you?&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Immutable collections&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Create an immutable list (as you might recall, every Java array is mutable,
  which can be a huge source of pain):&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;List&amp;lt;String&amp;gt; answers = ImmutableList.of("yes", "no", "maybe");&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;There's also a &lt;tt&gt;Builder&lt;/tt&gt; pattern for more complex constructions, and
  analogous classes &lt;tt&gt;Immutable{Map,Multimap,Set,SortedMap,SortedSet}&lt;/tt&gt;.

&lt;p&gt;&lt;b&gt;Collection factory methods&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Here's some standard Java code to instantiate a collection:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;List&amp;lt;Foo&amp;gt; foos = new ArrayList&amp;lt;Foo&amp;gt;()&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;Using the &lt;tt&gt;Lists&lt;/tt&gt; class, you can rewrite that as the following:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;List&amp;lt;Foo&amp;gt; foos = Lists.newArrayList()&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;Usually factory methods are a way for you to give the callee the flexibility
  of returning different classes at runtime. That's not the case here&amp;mdash;
  &lt;tt&gt;Lists.newArrayList&lt;/tt&gt; will always return an &lt;tt&gt;ArrayList&lt;/tt&gt;
  (unsurprisingly). But Java does type inference for a call of this type, so
  you save the hassle of having to repeat yourself by writing the generic type
  &lt;tt&gt;Foo&lt;/tt&gt; on both sides of the assignment, every time you create a new
  collection.&lt;/p&gt;
&lt;p&gt;There are analogous classes &lt;tt&gt;Maps&lt;/tt&gt; and &lt;tt&gt;Sets&lt;/tt&gt;, which also
  contain other useful utilities in addition to these factory methods.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Splitter&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Some simple illustrative examples for splitting a string using Guava's &lt;tt&gt;Splitter&lt;/tt&gt; class:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;Splitter.on(",").split("foo,bar,baz");&lt;br&gt;
// ==&gt; an iterable containing "foo", "bar", "baz"&lt;br&gt;
&lt;br&gt;
Splitter.on(",")&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.trimResults()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.omitEmptyStrings()&lt;br&gt;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.split("foo,bar   ,  baz,,,");&lt;br&gt;
// ==&gt; an iterable containing "foo", "bar", "baz"&lt;/tt&gt;&lt;/blockquote&gt;

&lt;p&gt;But wait, doesn't Java already do string splitting? Yes! Yes, it does.
  And this is how (emphasis mine):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;b&gt;String.split&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;public String[] split(String regex, int limit)&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;Splits this string around matches of the given regular expression.&lt;/p&gt;
&lt;p&gt;The array returned by this method contains each substring of this string that is terminated by another substring that matches the given expression or is terminated by the end of the string. The substrings in the array are in the order in which they occur in this string. If the expression does not match any part of the input then the resulting array has just one element, namely this string.&lt;/p&gt;
&lt;p&gt;The limit parameter controls the number of times the pattern is applied and therefore affects the length of the resulting array. If the limit n is greater than zero then the pattern will be applied at most n - 1 times, the array's length will be no greater than n, and the array's last entry will contain all input beyond the last matched delimiter. If n is non-positive then the pattern will be applied as many times as possible and the array can have any length. If n is zero then the pattern will be applied as many times as possible, the array can have any length, and &lt;b&gt;trailing empty strings will be discarded&lt;/b&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is a bizarre and unmemorable edge case in the API. I guarantee that upon finishing this paragraph, you will promptly forget about it until about two hours into debugging a failure caused by it. You can save yourself some grief if you just use &lt;tt&gt;Splitter&lt;/tt&gt;. &lt;b&gt;Stay away from &lt;tt&gt;String.split&lt;/tt&gt;&lt;/b&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-1027026198452330753?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/1027026198452330753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/09/guava.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1027026198452330753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1027026198452330753'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/09/guava.html' title='Guava'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6675218987148975030</id><published>2010-09-16T21:21:00.000-07:00</published><updated>2011-04-29T16:49:06.601-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Thinkpad TrackPoint Scrolling in Ubuntu Maverick/10.10</title><content type='html'>&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; these steps seem to work on Ubuntu Natty/11.04 for me, as well.&lt;/p&gt;
&lt;p&gt;My fellow citizens, our long national nightmare of having to use bad pointing devices is over.&lt;/p&gt;
&lt;p&gt;Starting with Ubuntu Maverick/10.10, configuring scrolling with the middle button and the TrackPoint is now really easy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install &lt;tt&gt;gpointing-device-settings&lt;/tt&gt; (&lt;tt&gt;sudo aptitude install gpointing-device-settings&lt;/tt&gt;)&lt;/li&gt;
&lt;li&gt;Run &lt;tt&gt;gpointing-device-settings &amp;&lt;/tt&gt;, enable the &lt;b&gt;Use wheel emulation&lt;/b&gt; using button &lt;b&gt;2&lt;/b&gt;, and enable both &lt;b&gt;vertical&lt;/b&gt; and &lt;b&gt;horizontal&lt;/b&gt; scrolling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style="text-align: center"&gt;&lt;img src="http://lh5.ggpht.com/_egN-3IJO0Xg/TJLoVpGcN6I/AAAAAAAANB4/qSKKgeQWH6E/gpointing-device-settings.png"&gt;&lt;/p&gt;
&lt;p&gt;(&lt;tt&gt;gpointing-device-settings&lt;/tt&gt; is not new but Maverick is the first time it has really worked well for me.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; some people are reporting that g-d-s settings are lost after suspend. If you run into this, you might try &lt;a href="http://psung.blogspot.com/2010/04/thinkpad-trackpoint-scrolling-in-ubuntu.html"&gt;these alternative instructions&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6675218987148975030?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6675218987148975030/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/09/thinkpad-trackpoint-scrolling-in-ubuntu.html#comment-form' title='43 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6675218987148975030'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6675218987148975030'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/09/thinkpad-trackpoint-scrolling-in-ubuntu.html' title='Thinkpad TrackPoint Scrolling in Ubuntu Maverick/10.10'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_egN-3IJO0Xg/TJLoVpGcN6I/AAAAAAAANB4/qSKKgeQWH6E/s72-c/gpointing-device-settings.png' height='72' width='72'/><thr:total>43</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-8308157574338359256</id><published>2010-09-14T23:28:00.000-07:00</published><updated>2010-09-14T23:28:07.294-07:00</updated><title type='text'>Designing for colorblindness</title><content type='html'>&lt;p&gt;Public service announcement: some 8% of men have some form of colorblindness.&lt;/p&gt;
&lt;p&gt;A couple of people have pointed me to &lt;a href="http://jfly.iam.u-tokyo.ac.jp/color/index.html"&gt;this nice article on colorblind-friendly design&lt;/a&gt;, by Masataka Okabe and Kei Ito. Useful reading for anyone who designs for print, presentations, or UIs.&lt;/p&gt;
&lt;p&gt;It's a good overview of the underlying theory/physiology of colorblindness and gives many tips for conveying information through channels other than color.&lt;/p&gt;
&lt;p&gt;The authors also provide this handy colorblind-friendly color palette:&lt;/p&gt;
&lt;p style="text-align: center"&gt;&lt;a href="http://jfly.iam.u-tokyo.ac.jp/color/index.html"&gt;&lt;img src="http://lh3.ggpht.com/_egN-3IJO0Xg/TJBjZDYuUeI/AAAAAAAANBk/W1MHNeBKZe4/pallete.jpg" style="border: 0"&gt;&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-8308157574338359256?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/8308157574338359256/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/09/designing-for-colorblindness.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8308157574338359256'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8308157574338359256'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/09/designing-for-colorblindness.html' title='Designing for colorblindness'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh3.ggpht.com/_egN-3IJO0Xg/TJBjZDYuUeI/AAAAAAAANBk/W1MHNeBKZe4/s72-c/pallete.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5571331846295456385</id><published>2010-09-10T01:28:00.000-07:00</published><updated>2010-09-29T22:05:25.949-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Backups and rdiff-backup</title><content type='html'>&lt;p&gt;I always thought nearlyfreespeech.net's advice on backups was good advice:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;You should adopt a backup policy that assumes we are storing crates of sweaty dynamite on top of the servers that hold your important data. (Even though we aren't.) &lt;em&gt;[&lt;a href="http://faq.nearlyfreespeech.net/full/backups#backups"&gt;NFSN FAQs&lt;/a&gt;]&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;If you only have one copy of something, stop what you are doing, obtain a disk, and replicate it.&lt;/p&gt;
&lt;p&gt;Here are some brief notes on my backup setup, including some things I've learned since &lt;a href="http://psung.blogspot.com/2008/03/making-backups-instructions-for.html"&gt;I last wrote about backups&lt;/a&gt;. (I had a disk failure last December and restored everything from backup. No tears, no sweat. In fact the exact same thing seems to happen about once every year, which I suppose is a good testimonial. I'm probably due for a disk failure real soon now.)&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;My first line of defense is backing up to a secondary HDD in my machine. I mostly use &lt;tt&gt;&lt;a href="http://rdiff-backup.nongnu.org/"&gt;rdiff-backup&lt;/a&gt;&lt;/tt&gt; now (and only &lt;tt&gt;rsync&lt;/tt&gt; for huge files, like disk images). This system seems to work well. &lt;tt&gt;rdiff-backup&lt;/tt&gt; creates reverse diffs on each backup so you can retrieve old versions. All the diffs go in the &lt;tt&gt;rdiff-backup-data&lt;/tt&gt; subdir; if you remove that you just get a plain mirror, like what &lt;tt&gt;rsync&lt;/tt&gt; would do.&lt;/li&gt;
  &lt;li&gt;I wrote a FUSE filesystem, &lt;a href="http://psung.blogspot.com/2010/06/rdiff-snapshot-fs.html"&gt;rdiff-snapshot-fs&lt;/a&gt;, that displays rdiff's repository format as a series of mirrors in order to make it easier to browse historical snapshots. Doing a restore of individual files from time to time is key to ensuring your system is working when you &lt;em&gt;really&lt;/em&gt; need it.&lt;/li&gt;
  &lt;li&gt;Rather than scheduling backups with &lt;tt&gt;cron&lt;/tt&gt; and having to leave my computer on at night or, alternatively, having backups happen while I'm working, I bound a hotkey to a script that backs up and then &lt;a href="http://psung.blogspot.com/2010/09/assorted-notes.html"&gt;puts the computer into suspend&lt;/a&gt;. I run it when I leave the computer for the day, every day.&lt;/li&gt;
  &lt;li&gt;I also &lt;tt&gt;rsync&lt;/tt&gt; to other backup backup locations, including a portable HDD that stays in a safe place when I'm not using it.&lt;/li&gt;
  &lt;li&gt;When &lt;em&gt;restoring&lt;/em&gt; from a mirror, the &lt;tt&gt;&lt;b&gt;-c&lt;/b&gt;&lt;/tt&gt; flag to &lt;tt&gt;rsync&lt;/tt&gt; is useful. It makes &lt;tt&gt;rsync&lt;/tt&gt; compare the checksum of the data being copied back with the checksum of the original. Then if you have multiple backups of the same stuff you can easily identify and reconcile any differences between them.&lt;/li&gt;
  &lt;li&gt;I did try &lt;tt&gt;&lt;a href="http://rsnapshot.org/"&gt;rsnapshot&lt;/a&gt;&lt;/tt&gt;. Unfortunately it caused my system load average to shoot through the roof, making the system unresponsive while backups were being made. I have no idea why this is but a few other people have reported the same thing.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5571331846295456385?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5571331846295456385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/09/backups-and-rdiff-backup.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5571331846295456385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5571331846295456385'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/09/backups-and-rdiff-backup.html' title='Backups and rdiff-backup'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4481683751628362005</id><published>2010-09-10T01:18:00.000-07:00</published><updated>2010-09-29T10:42:49.158-07:00</updated><title type='text'>Thinkpad close calls</title><content type='html'>&lt;p&gt;(I am not on Lenovo's payroll, just a happy user.)&lt;/p&gt;

&lt;p&gt;I just got a new Thinkpad X201, and will comment on it more in due time. But
  while I was waiting for it to arrive, something happened that reminded me why
  I don't have to think twice about buying or recommending Thinkpads.&lt;/p&gt;

&lt;p&gt;A friend of mine had spilled a glass of water on her Thinkpad. Well,
  Thinkpads have &lt;a href="http://lenovoblogs.com/designmatters/?p=40"&gt;drainage
  holes under the keyboard&lt;/a&gt; so the bulk of the water is routed harmlessly
  out of the bottom. So this was a minor incident. The laptop wouldn't boot for
  about a day. But once it had dried off, it was back in business. No prepaid
  shipping box, no trips to the repair store. No discernible lasting damage.
  None.&lt;/p&gt;

&lt;p&gt;Water damage must be one of the most common causes of laptop death. And yet,
  most computers (Thinkpads excepted) ship with a keyboard that goes
  &lt;em&gt;zap&lt;/em&gt; when you spill something on it. It is astonishing that the
  spill-through keyboard (or equivalent) is not a standard feature on laptops.
  It does significantly increase the expected lifetime of your computer.&lt;/p&gt;

&lt;p&gt;And it's not just water damage, either. My own X61s has also been through
  quite a few nasty drops and falls. I fell &lt;em&gt;on&lt;/em&gt; it once when I slipped
  on ice. No ill effects. For the laptop, anyway. And the thing is everyone
  just &lt;em&gt;expects&lt;/em&gt; that level of durability from Thinkpads. There is some
  serious quality engineering going on at Lenovo.&lt;/p&gt;

&lt;p&gt;For crying out loud, the Thinkpads pass the freaking &lt;a
  href="http://www.crunchgear.com/2009/02/24/74521/"&gt;military spec tests for
  ruggedness&lt;/a&gt;. And just for fun, &lt;a
  href="http://www.youtube.com/watch?v=wwCO740QB4U"&gt;here's a video of a guy
  driving a motorbike over a Thinkpad&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;These things are unbelievable. They are really built to last.&lt;/b&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4481683751628362005?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4481683751628362005/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/09/thinkpad-close-calls.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4481683751628362005'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4481683751628362005'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/09/thinkpad-close-calls.html' title='Thinkpad close calls'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7495495411026211457</id><published>2010-09-09T23:56:00.000-07:00</published><updated>2010-09-09T23:56:49.794-07:00</updated><title type='text'>Google Web Toolkit again</title><content type='html'>&lt;p&gt;&lt;a href="http://code.google.com/webtoolkit/"&gt;Google Web Toolkit&lt;/a&gt; 2.0 was released some months back. &lt;a
  href="http://psung.blogspot.com/2009/08/google-web-toolkit-and-javajs.html"&gt;As
  I've said before&lt;/a&gt;, I think GWT or something like it is really the
  &lt;em&gt;right&lt;/em&gt; way to write web apps. The optimized/compressed/inlined
  Javascript you want to be running in any nontrivial web app is so far from
  the readable and modular code that you want to actually be &lt;em&gt;writing&lt;/em&gt;
  that it really demands an intermediate translation layer. This most recent
  release really just cements that fact.&lt;/p&gt;

&lt;p&gt;For example, new in GWT 2.0 is &lt;em&gt;code splitting&lt;/em&gt;, a feature that helps
  to reduce page load times. You define some &lt;em&gt;split points&lt;/em&gt; in your
  app&amp;mdash; points during execution where the client can make a round-trip to
  the server to fetch more code. GWT breaks off parts of your application that
  aren't needed when the app initially loads, and only downloads them when the
  app needs to cross the split point. Sure, you could compute, by hand, the
  transitive closure of all the components of your application that aren't past
  any split point, and shuffle your code around between files, and dread having
  to redo all that every time you do some refactoring. But you have better
  things to do.&lt;/p&gt;

&lt;p&gt;It's true that Javascript engines are getting faster every week, so the
  value of highly optimizing your Javascript ahead of time may seem rather
  uncertain. But GWT also does things like automatically creating image sprites
  on your behalf, so your app can pull down all its images without the overhead
  of multiple HTTP requests. No Javascript engine can make excessive image
  requests fast. And in version 2.0, GWT does something similar for
  stylesheets. Again, all stuff you could do by hand&amp;mdash; if you were highly
  disciplined, or a robot.&lt;/p&gt;

&lt;p&gt;Further reading: &lt;a href="http://timepedia.blogspot.com/2009/12/gwt-20-so-good-its-ridiculous.html"&gt;More
    new features in GWT 2.0&lt;/a&gt;
  and &lt;a href="http://code.google.com/webtoolkit/doc/latest/ReleaseNotes.html"&gt;stuff
    slated for 2.1&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7495495411026211457?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7495495411026211457/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/09/google-web-toolkit-again.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7495495411026211457'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7495495411026211457'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/09/google-web-toolkit-again.html' title='Google Web Toolkit again'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7446843744822705938</id><published>2010-09-09T23:27:00.000-07:00</published><updated>2010-09-09T23:27:49.313-07:00</updated><title type='text'>Assorted Notes</title><content type='html'>&lt;p&gt;Many random notes (some for my own reference), each of which is too short to
  warrant a full blog post:&lt;/p&gt;

&lt;b&gt;PSA: remote tab completion&lt;/b&gt;

&lt;p&gt;If you have set up passwordless SSH login to some host, then
  &lt;tt&gt;bash-completion&lt;/tt&gt; in Debian/Ubuntu (which is enabled by default, I
  think) automatically completes remote paths as arguments to &lt;tt&gt;scp&lt;/tt&gt;. For
  example, pressing &lt;tt&gt;TAB&lt;/tt&gt; after the following does exactly what it ought
  to, namely, display files within &lt;tt&gt;/path/to/whatever&lt;/tt&gt; on the host
  &lt;tt&gt;example.com&lt;/tt&gt;:&lt;/p&gt;

&lt;blockquote&gt;&lt;tt&gt;scp example.com:/path/to/whatever/&lt;/tt&gt;&lt;/blockquote&gt;

&lt;b&gt;Emacs: &lt;tt&gt;dired-jump&lt;/tt&gt;&lt;/b&gt;

&lt;p&gt;Ever find yourself wanting to rename or move a file while you're editing it?
  &lt;tt&gt;M-x&amp;nbsp;dired-jump&lt;/tt&gt; brings up a &lt;tt&gt;dired&lt;/tt&gt; view of the directory
  containing the current file (you may need to &lt;tt&gt;(require&amp;nbsp;'dired-x)&lt;/tt&gt;
  first). Press &lt;tt&gt;R&lt;/tt&gt; ("Rename") and type the new path.&lt;/p&gt;

&lt;p&gt;The best part is that the original editing buffer gets its path updated
  automatically (and its buffer name too, if you changed the basename), so you
  can get straight back to work&amp;mdash; no need to close and reopen the
  file.&lt;/p&gt;

&lt;b&gt;Suspending from the command line&lt;/b&gt;

&lt;p&gt;On Ubuntu 10.04 Lucid, you can suspend the machine programmatically by
  installing &lt;tt&gt;acpitool&lt;/tt&gt; and then running the following:&lt;/p&gt;

&lt;blockqoute&gt;&lt;tt&gt;gnome-screensaver-command --lock  # Optional- locks the screen&lt;br&gt;
    sudo /usr/bin/acpitool -s&lt;/tt&gt;&lt;/blockqoute&gt;

&lt;p&gt;To avoid having to enter my password every time for &lt;tt&gt;acpitool&lt;/tt&gt;, I
  whitelisted that command in &lt;tt&gt;sudo&lt;/tt&gt; for use without a password. You can
  do this by running &lt;tt&gt;sudo visudo&lt;/tt&gt; and adding the following line at the
  end of the file:&lt;/p&gt;

&lt;blockquote&gt;&lt;tt&gt;%admin ALL = NOPASSWD: /usr/bin/acpitool -s&lt;/tt&gt;&lt;/blockquote&gt;

&lt;p&gt;Sources: &lt;a href="http://nixliving.blogspot.com/2010/05/acpitool-as-alternative-suspend-method.html"&gt;Linux Living&lt;/a&gt;. Also see:
  &lt;a href="http://ubuntuforums.org/showthread.php?t=410570"&gt;instructions for
  previous Ubuntu versions&lt;/a&gt;; &lt;tt&gt;pm-suspend(8)&lt;/tt&gt;.&lt;/p&gt;

&lt;b&gt;VirtualBox&lt;/b&gt;

&lt;p&gt;I've been using VirtualBox (&lt;tt&gt;aptitude install virtualbox-ose&lt;/tt&gt;) to run
  virtual machines of various GNU/Linux flavors (for me, it's primarily useful
  for making sure Zeya works on different platforms and configurations), and I
  am generally pleased with it. A couple of tips for setting up VMs for maximum
  effectiveness:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The &lt;tt&gt;virtualbox-ose-guest-x11&lt;/tt&gt; package, when installed &lt;em&gt;on the
      guest&lt;/em&gt;, provides a driver for the virtual display device. This seems
    to be necessary (and sufficient) to get not-crappy graphics
    performance.&lt;/li&gt;
  &lt;li&gt;Configuring your VM to use &lt;em&gt;bridged networking&lt;/em&gt; makes the VM
    appear as a device on the host's network, for example, it will pick up an
    IP address from your local DHCP server.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7446843744822705938?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7446843744822705938/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/09/assorted-notes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7446843744822705938'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7446843744822705938'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/09/assorted-notes.html' title='Assorted Notes'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-180047272805595226</id><published>2010-08-17T01:02:00.000-07:00</published><updated>2010-08-17T01:02:45.804-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>wdired and renaming into nonexistent directories</title><content type='html'>&lt;p&gt;(For the uninitiated, &lt;tt&gt;wdired&lt;/tt&gt; is an indispensable emacs mode that lets you rename files in a directory just by editing their filenames in a buffer.)&lt;/p&gt;
&lt;p&gt;Joakim Verona wrote &lt;a href="http://www.emacswiki.org/emacs/WDired"&gt;a nifty patch against &lt;tt&gt;wdired&lt;/tt&gt;&lt;/a&gt; that allows you to rename even to paths in directories that don't exist yet (emacs creates them for you when you finalize the operation). As an example of where this might be useful, suppose you have a directory like this:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;  /home/phil/tempfiles:
  total used in directory 60K available 413675080
  -rw-r--r--  1 phil phil 318K 2009-12-31 19:00 &lt;b&gt;20091231.jpg&lt;/b&gt;
  -rw-r--r--  1 phil phil 320K 2010-01-01 19:00 &lt;b&gt;20100101.jpg&lt;/b&gt;
  -rw-r--r--  1 phil phil 305K 2010-01-02 19:00 &lt;b&gt;20100102.jpg&lt;/b&gt;
  [...]&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Say you change that to the following (for instance, using &lt;tt&gt;M-x string-rectangle&lt;/tt&gt;, among other alternatives):&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;  /home/phil/tempfiles:
  total used in directory 60K available 413675080
  -rw-r--r--  1 phil phil 318K 2009-12-31 19:00 &lt;b&gt;2009/12/31.jpg&lt;/b&gt;
  -rw-r--r--  1 phil phil 320K 2010-01-01 19:00 &lt;b&gt;2010/01/01.jpg&lt;/b&gt;
  -rw-r--r--  1 phil phil 305K 2010-01-02 19:00 &lt;b&gt;2010/01/02.jpg&lt;/b&gt;
  [...]&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;When you save, your files are now neatly organized in a year/month/day directory structure. This is the closest thing to &lt;em&gt;magic&lt;/em&gt; I've done on my computer this month.&lt;/p&gt;
&lt;p&gt;I've made some minor updates to Joakim's patch to fix bit-rot and conditionalize this behavior on a variable.&lt;/p&gt;
&lt;p style="text-align: center"&gt;&lt;a href="http://web.psung.name/emacstips/wdired-rename-to-nonexistent-directories.patch"&gt;&lt;b&gt;wdired-rename-to-nonexistent-directories.patch&lt;/b&gt; (1.6kb)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;As an aside, I think learning about &lt;tt&gt;wdired&lt;/tt&gt; turned on a lightbulb in my head that changed my understanding of Emacs. Yes, emacs is a text editor. But its power comes, in part, from the scores of major modes that let you interact with many different kinds of resources (e.g. your filesystem, as with &lt;tt&gt;wdired&lt;/tt&gt;) under the guise of editing text (which you can think of as supplying a common abstraction over all those resources). Once you learn how to use, say, regexp search and replace, you can take advantage of that power when editing text files, but also when renaming/reorganizing files or composing mail or whatnot. Emacs is a text editor, but &lt;em&gt;text&lt;/em&gt; doesn't just mean &lt;em&gt;files&lt;/em&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-180047272805595226?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/180047272805595226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/08/wdired-and-renaming-into-nonexistent.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/180047272805595226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/180047272805595226'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/08/wdired-and-renaming-into-nonexistent.html' title='wdired and renaming into nonexistent directories'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-8068876600698205727</id><published>2010-08-11T00:16:00.000-07:00</published><updated>2010-08-11T00:16:15.857-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computational research'/><category scheme='http://www.blogger.com/atom/ns#' term='unix'/><title type='text'>GNU Parallel</title><content type='html'>&lt;p&gt;I figured this was worth sharing because I myself had written &lt;em&gt;two&lt;/em&gt; (fairly lame) clones of this program before I discovered it.&lt;/p&gt;
&lt;p&gt;Sometimes I find myself composing and running huge shell scripts, like the following:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$ cat process-files.sh
sox input/foo.ogg output/foo.ogg channels 1
sox input/bar.ogg output/bar.ogg channels 1
sox input/baz.ogg output/baz.ogg channels 1
sox input/quux.ogg output/quux.ogg channels 1
# more of the same, for perhaps hundreds of lines...&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;small&gt;(Aside: why not &lt;tt&gt;xargs&lt;/tt&gt;? For complicated tasks, it can be error-prone or just plain insufficient. Moreover, there's a lot of value in being able to just &lt;em&gt;look&lt;/em&gt; at the script and see &lt;em&gt;exactly&lt;/em&gt; what is going to be executed on your behalf, especially for one-off tasks. If you know emacs macros, scripts like this are not onerous at all to generate anyway.)&lt;/small&gt;&lt;/p&gt;
&lt;p&gt;If you have a sequence of tasks like this that can run independently (and they are CPU-bound), then it pays to distribute the tasks over all your CPU cores. Here's where &lt;a href="http://www.gnu.org/software/parallel/" style="font-weight: bold"&gt;GNU Parallel&lt;/a&gt; comes in handy. Just pipe into it the commands you want to execute:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$ parallel -j4 &lt; process-files.sh&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Now &lt;tt&gt;parallel&lt;/tt&gt; runs up to 4 tasks concurrently, starting up a new one when each one finishes (just as if you had a queue and a pool of 4 workers). What an elegant interface.&lt;/p&gt;
&lt;p&gt;GNU Parallel has a bunch of more advanced features that are worth checking out, for example, preserving the proper ordering of standard output across tasks (to maintain the illusion of sequential-ness), or showing an ETA.&lt;/p&gt;
&lt;p&gt;GNU Parallel is not in the official Debian/Ubuntu repos (as far as I can tell) but it is a snap to build from source, and it's the sort of thing I'd want floating around in my &lt;tt&gt;~/bin&lt;/tt&gt; everywhere I work.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-8068876600698205727?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/8068876600698205727/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/08/gnu-parallel.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8068876600698205727'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8068876600698205727'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/08/gnu-parallel.html' title='GNU Parallel'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5277061790191518520</id><published>2010-07-18T10:19:00.000-07:00</published><updated>2010-09-29T22:05:25.949-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Extracting the audio track from videos, and downmixing</title><content type='html'>&lt;p&gt;On Ubuntu/Debian, you can use &lt;tt&gt;ffmpeg&lt;/tt&gt; (in the package of the same name) to extract the audio only from video files:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;$ ffmpeg -i input.ogm -ab 128k -vn output.ogg&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;tt&gt;ffmpeg&lt;/tt&gt; detects the input and output formats automatically, so you can also convert to an MP3 (for example) just by specifying an output filename of the appropriate extension.&lt;/p&gt;
&lt;p&gt;When converting audio for listening while working out or while traveling, it's also useful to downmix stereo to mono so you can listen with just one earbud without missing anything:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;$ ffmpeg -i input.ogm -ab 128k &lt;b style="background-color: #ddcccc"&gt;-ac 1&lt;/b&gt; -vn output.ogg&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;(Thanks to &lt;a href="http://www.renemoser.net/2009/11/convert-avi-into-mp3-on-linux/"&gt;Rene Moser&lt;/a&gt; for the pointer. Also check out &lt;a href="http://sox.sourceforge.net"&gt;&lt;tt&gt;sox&lt;/tt&gt;&lt;/a&gt; if you are looking to apply more sophisticated audio transformations.)&lt;/p&gt;
&lt;p&gt;Further reading: &lt;a href="http://www.ffmpeg.org/ffmpeg-doc.html"&gt;&lt;tt&gt;ffmpeg&lt;/tt&gt; command-line tool documentation&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5277061790191518520?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5277061790191518520/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/07/extracting-audio-track-from-videos-and.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5277061790191518520'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5277061790191518520'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/07/extracting-audio-track-from-videos-and.html' title='Extracting the audio track from videos, and downmixing'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-1928656399046717232</id><published>2010-07-11T09:07:00.000-07:00</published><updated>2010-07-11T09:07:24.321-07:00</updated><title type='text'>The first step is admitting you have a problem</title><content type='html'>&lt;p&gt;A few months ago I glanced at my &lt;a href="http://googlereader.blogspot.com/2007/01/i-like-big-charts-and-i-cannot-lie.html"&gt;Google Reader Trends page&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;From your 188 subscriptions, over the last 30 days you read 10,075 items...&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Seeing a five-digit number there frightened me a bit, especially because I am not Robert Scoble&lt;sup&gt;1&lt;/sup&gt; and staying on top of tech news is not my day job. Since then I've made three changes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I'm checking Google Reader only once a week.&lt;/li&gt;
&lt;li&gt;I've culled my list of subscriptions, reducing the number of items per day by about 70%.&lt;/li&gt;
&lt;li&gt;For the high-volume feeds that remain, I read them in &lt;a href="http://googlereader.blogspot.com/2009/10/reading-gets-personal-with-popular.html"&gt;sort by magic&lt;/a&gt; order and don't read all of the items if I don't have time.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just the first item, dealing with the news in batch mode, is sufficient to free up a big chunk of time (and mitigate the sensation of drowning). I still get news from other sources on a more-than-once-weekly basis&amp;mdash; mostly, Google Buzz and email lists&amp;mdash; and I'd like to improve the way I deal with those, too, but at this time they have far better S/N ratio and lower volume.&lt;/p&gt;
&lt;p&gt;In my ideal world, for each feed I could turn a dial to say "show me the no-more-than-&lt;em&gt;N&lt;/em&gt; most popular items per day for this feed". But &lt;em&gt;sort by magic&lt;/em&gt; comes pretty close to what I want.&lt;/p&gt;
&lt;p&gt;&lt;sup&gt;1&lt;/sup&gt; Scoble famously follows &lt;a href="http://twitter.com/scobleizer"&gt;over 18,000(!) people&lt;/a&gt; on Twitter.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-1928656399046717232?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/1928656399046717232/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/07/first-step-is-admitting-you-have.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1928656399046717232'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1928656399046717232'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/07/first-step-is-admitting-you-have.html' title='The first step is admitting you have a problem'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-3108729778502718366</id><published>2010-07-10T14:39:00.000-07:00</published><updated>2010-07-10T14:39:06.905-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zeya'/><title type='text'>Zeya in Linux Journal</title><content type='html'>&lt;p&gt;Amit Saha wrote &lt;a href="http://www.linuxjournal.com/content/serve-your-music-zeya"&gt;a nice article&lt;/a&gt; about Zeya in Linux Journal. It's pretty much Zeya's missing tutorial and design doc (not to mention, a review and a rundown of the alternatives). Thanks, Amit!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-3108729778502718366?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/3108729778502718366/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/07/zeya-in-linux-journal.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/3108729778502718366'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/3108729778502718366'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/07/zeya-in-linux-journal.html' title='Zeya in Linux Journal'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6620212525681390382</id><published>2010-06-17T02:15:00.000-07:00</published><updated>2010-09-29T22:05:25.950-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='rdiff-snapshot-fs'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>rdiff-snapshot-fs</title><content type='html'>&lt;p&gt;I use &lt;tt&gt;&lt;a href="http://www.nongnu.org/rdiff-backup/"&gt;rdiff-backup&lt;/a&gt;&lt;/tt&gt; for backups. It creates a mirror of your data, just like plain old &lt;tt&gt;rsync&lt;/tt&gt;, but also stores a series of reverse diffs that lets you restore historical versions of each file. For the most part it works well, but the interface for browsing and restoring from backups is somewhat clunky:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$ # List all snapshots
$ &lt;b&gt;rdiff-backup -l /backup&lt;/b&gt;
Found 3 increments:
    increments.2010-06-01T23:00:00-07:00.dir   Tue Jun  1 23:00:00 2010
    increments.2010-06-02T23:00:00-07:00.dir   Wed Jun  2 23:00:00 2010
    increments.2010-06-03T23:00:00-07:00.dir   Thu Jun  3 23:00:00 2010
Current mirror: Fri Jun  4 23:00:00 2010
$ # List contents of a snapshot
$ # (note, lists specified dir recursively)
$ &lt;b&gt;rdiff-backup --list-at-time 2010-06-01T23:00:00 /backup/foo/bar&lt;/b&gt;
foo/bar/one
foo/bar/two
foo/bar/more/three
foo/bar/more/four
$ # Restore a file from backup
$ &lt;b&gt;rdiff-backup -r 2010-06-01T23:00:00 /backup/foo/bar/one ~/one.restore&lt;/b&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;I wrote &lt;a href="http://web.psung.name/rdiff-snapshot-fs"&gt;&lt;tt&gt;&lt;b&gt;rdiff-snapshot-fs&lt;/b&gt;&lt;/tt&gt;&lt;/a&gt;, which is an alternative to &lt;tt&gt;rdiff-backup&lt;/tt&gt;'s restore interface. It's a virtual filesystem (powered by &lt;a href="http://fuse.sourceforge.net/"&gt;FUSE&lt;/a&gt;) that lets you browse all your snapshots and their contents. Now you can examine each snapshot as if it were backed by a real mirror:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$ &lt;b&gt;./rdiff-snapshot-fs.py /backup /view&lt;/b&gt;
$ &lt;b&gt;ls /view&lt;/b&gt;
2010-06-01T23:00:00-07:00
2010-06-02T23:00:00-07:00
2010-06-03T23:00:00-07:00
$ &lt;b&gt;ls /view/2010-06-01T23:00:00-07:00/foo/bar&lt;/b&gt;
one
two
more
$ &lt;b&gt;cp /view/2010-06-01T23:00:00-07:00/foo/bar/one ~/one.restore&lt;/b&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Some background: another tool, called &lt;a href="http://code.google.com/p/archfs/"&gt;archfs&lt;/a&gt;, provides similar functionality, but it has performance issues, and I never got it to successfully load my backup repository (granted, my homedir backup repo has 400 snapshots and a current mirror size of 450GB). I concur with &lt;a href="http://jmtd.net/computing/software/rdifffs/"&gt;Jon Dowland's assessment&lt;/a&gt; that the problem stems from archfs trying to reconstruct historical snapshot data up front before it's needed. (Many problems in software, as well as in life, are really problems caused by being insufficiently lazy!)&lt;/p&gt;
&lt;p&gt;More info about &lt;tt&gt;rdiff-snapshot-fs&lt;/tt&gt;, including how to obtain the source, can be found at &lt;a href="http://web.psung.name/rdiff-snapshot-fs"&gt;&lt;tt&gt;http://web.psung.name/rdiff-snapshot-fs&lt;/tt&gt;.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;(By the way, FUSE is really interesting to play with and FUSE-Python makes it a snap to get started. More remarks about this soon, possibly.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Disclaimer:&lt;/b&gt; This is something I cooked up in my spare time. &lt;tt&gt;rdiff-snapshot-fs&lt;/tt&gt; is liable to eat your data and scare your pets. The file sizes and modes that it reports are known to be unreliable under certain circumstances (though the file data itself is generated correctly, as far as I can tell). But, if you know no fear, you may find it somewhat more useful than the standard &lt;tt&gt;rdiff-backup&lt;/tt&gt; interface.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6620212525681390382?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6620212525681390382/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/06/rdiff-snapshot-fs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6620212525681390382'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6620212525681390382'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/06/rdiff-snapshot-fs.html' title='rdiff-snapshot-fs'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-631790682236009010</id><published>2010-04-20T20:32:00.000-07:00</published><updated>2010-10-14T00:07:05.600-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Thinkpad TrackPoint Scrolling in Ubuntu Lucid/10.04</title><content type='html'>&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; for (easier) instructions for Ubuntu Maverick/10.10 and later, &lt;a href="http://psung.blogspot.com/2010/09/thinkpad-trackpoint-scrolling-in-ubuntu.html"&gt;click here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Another Ubuntu release, another set of X.org shakeups.&lt;/p&gt;
&lt;p&gt;Some things in X changed in Lucid (&lt;tt&gt;xorg 1:7.5+5&lt;/tt&gt; and higher), breaking existing Thinkpad TrackPoint scrolling configurations that modify files in &lt;tt&gt;/etc/hal/fdi/policy&lt;/tt&gt; (like those you may have seen in &lt;a href="http://psung.blogspot.com/2008/09/scrolling-with-thinkpads-trackpoint-in.html"&gt;this previous post&lt;/a&gt;). You can use &lt;tt&gt;gpointing-device-settings&lt;/tt&gt; to apply the same policy, but I found that even that stops working after a suspend/resume cycle.&lt;/p&gt;
&lt;p&gt;Samson Yeung pointed out to me the following fix which can be applied on Ubuntu Lucid/10.04:&lt;/p&gt;
&lt;p&gt;Create a new file &lt;tt&gt;/usr/lib/X11/xorg.conf.d/20-thinkpad.conf&lt;/tt&gt; with the following contents (on Ubuntu Maverick/10.10 and later, save the file to &lt;tt&gt;/usr/&lt;b&gt;share&lt;/b&gt;/X11/xorg.conf.d/20-thinkpad.conf&lt;/tt&gt; instead):&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;Section "InputClass"
    Identifier "Trackpoint Wheel Emulation"
    MatchProduct "TrackPoint"
    MatchDevicePath "/dev/input/event*"
    Driver "evdev"
    Option "EmulateWheel" "true"
    Option "EmulateWheelButton" "2"
    Option "Emulate3Buttons" "false"
    Option "XAxisMapping" "6 7"
    Option "YAxisMapping" "4 5"
EndSection&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Then restart X.&lt;/p&gt;
&lt;p&gt;The configuration above works for both Thinkpad laptops with TrackPoints and the Thinkpad TrackPoint keyboard.&lt;/p&gt;
&lt;p&gt;Source: instructions derived from &lt;a href="http://dlv.blogspot.com/2010/04/udev-xorgconfd-snippet.html"&gt;these instructions by Samson Yeung&lt;/a&gt;. Thanks, Samson!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-631790682236009010?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/631790682236009010/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/04/thinkpad-trackpoint-scrolling-in-ubuntu.html#comment-form' title='87 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/631790682236009010'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/631790682236009010'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/04/thinkpad-trackpoint-scrolling-in-ubuntu.html' title='Thinkpad TrackPoint Scrolling in Ubuntu Lucid/10.04'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>87</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2738914072803090108</id><published>2010-03-06T11:05:00.000-08:00</published><updated>2010-03-06T11:37:07.510-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Resolving conflicts (in version control)</title><content type='html'>&lt;p&gt;When Git (or another VCS) attempts to apply a patch that doesn't apply cleanly, it will defer to you, the user, to figure out the right thing to do. Usually you get, dumped in your lap, a file that has all these funny conflict markers in it, showing alternative versions of the content:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;    &amp;lt;action name="Execute"&amp;gt;&amp;lt;execute&amp;gt;google-chrome&amp;lt;/execute&amp;gt;&amp;lt;/action&amp;gt;
  &amp;lt;/keybind&amp;gt;
  &amp;lt;keybind key="W-s-b"&amp;gt;
&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt; HEAD
    &amp;lt;action name="Execute"&amp;gt;&amp;lt;execute&amp;gt;firefox-3.6&amp;lt;/execute&amp;gt;&amp;lt;/action&amp;gt;
=======
    &amp;lt;action name="Execute"&amp;gt;&amp;lt;execute&amp;gt;firefox-3.7&amp;lt;/execute&amp;gt;&amp;lt;/action&amp;gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; f50523b...
  &amp;lt;/keybind&amp;gt;
  &amp;lt;keybind key="W-a"&amp;gt;
    &amp;lt;action name="Execute"&amp;gt;&amp;lt;execute&amp;gt;rhythmbox&amp;lt;/execute&amp;gt;&amp;lt;/action&amp;gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;You can edit that file by hand to get the state you want, but Emacs has a specialized mode for resolving conflicts. Type &lt;b&gt;&lt;tt&gt;M&amp;#8209;x&amp;nbsp;vc&amp;#8209;resolve&amp;#8209;conflicts&lt;/tt&gt;&lt;/b&gt; and you get a three-paned frame like the following:&lt;/p&gt;
&lt;p&gt;&lt;img src="http://lh4.ggpht.com/_egN-3IJO0Xg/S5H8gwTDaFI/AAAAAAAAE10/IeJwVvvN13k/s640/merge.png"&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Press &lt;b&gt;&lt;tt&gt;n&lt;/tt&gt;&lt;/b&gt; and &lt;b&gt;&lt;tt&gt;p&lt;/tt&gt;&lt;/b&gt; to move between diff hunks.&lt;/li&gt;
  &lt;li&gt;For each hunk you can press &lt;b&gt;&lt;tt&gt;a&lt;/tt&gt;&lt;/b&gt; or &lt;b&gt;&lt;tt&gt;b&lt;/tt&gt;&lt;/b&gt; to transfer the version from the left or right side, respectively, to the output. You can leave the conflicted versions if there's something you really need to fix up by hand.&lt;/li&gt;
  &lt;li&gt;Press &lt;b&gt;&lt;tt&gt;q&lt;/tt&gt;&lt;/b&gt; when you're done. Emacs returns you to your fixed-up file. Save it.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2738914072803090108?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2738914072803090108/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/03/resolving-conflicts-in-version-control.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2738914072803090108'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2738914072803090108'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/03/resolving-conflicts-in-version-control.html' title='Resolving conflicts (in version control)'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_egN-3IJO0Xg/S5H8gwTDaFI/AAAAAAAAE10/IeJwVvvN13k/s72-c/merge.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6552569606400968764</id><published>2010-03-06T10:05:00.000-08:00</published><updated>2010-04-13T20:24:32.087-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Some Emacs macro tricks</title><content type='html'>&lt;p&gt;Keyboard macros are the Emacs feature that I wish every program had. Especially web browsers: having to carry out repetitive tasks in web apps always feels to me like a throwback to a less civilized era.&lt;/p&gt;
&lt;p&gt;(&lt;a href="http://web.psung.name/emacstips/essential.html"&gt;More information about keyboard macros, for the uninitiated&lt;/a&gt;: see #2.)&lt;/p&gt;
&lt;p&gt;Here are some useful macro-related commands that I recently learned to use:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Extending a macro&lt;/b&gt;. If you record a macro, then realize you forgot to add an important step at the end, you don't have to re-record it. &lt;tt&gt;C-u F3&lt;/tt&gt; replays the last macro and then lets you tack on more commands to the end of it.&lt;/p&gt;
&lt;p&gt;For example, &lt;tt&gt;C-u F3 RET F4&lt;/tt&gt; replays the last macro and then appends &lt;tt&gt;RET&lt;/tt&gt; to the end of it. (You can also use &lt;tt&gt;C-u C-u F3 ... F4&lt;/tt&gt; to extend a macro without replaying it again first.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Editing a macro&lt;/b&gt;. For more intensive fixes or changes to macros, you can edit your most recent macro with &lt;tt&gt;C-x C-k C-e&lt;/tt&gt; (&lt;tt&gt;kmacro-edit-macro-repeat&lt;/tt&gt;). You get a buffer like the following, and you can remove keystrokes or add new ones:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;pre&gt;;; Keyboard Macro Editor.
;; Press C-c C-c to finish; press C-x k RET to cancel.
;; Original keys: ESC c ESC f ESC f ESC f C-d RET&lt;

Command: last-kbd-macro
Key: none

Macro:

ESC c   ;; capitalize-word
ESC f   ;; forward-word
ESC f   ;; forward-word
ESC f   ;; forward-word
C-d   ;; delete-char
RET   ;; newline&lt;/pre&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;b&gt;Creating a macro from your keyboard history&lt;/b&gt;. If you just performed some task that you'd like to repeat, but didn't have the foresight to start recording a macro before you started, all is not lost. &lt;tt&gt;C-x C-k l&lt;/tt&gt; (&lt;tt&gt;kmacro-edit-lossage&lt;/tt&gt;) brings up a buffer (like the edit buffer above) containing your most recent 300 keystrokes, which you can pare down to create a new macro.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6552569606400968764?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6552569606400968764/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/03/some-emacs-macro-tricks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6552569606400968764'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6552569606400968764'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/03/some-emacs-macro-tricks.html' title='Some Emacs macro tricks'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2928460614973917844</id><published>2010-03-01T00:14:00.000-08:00</published><updated>2010-03-03T00:13:41.775-08:00</updated><title type='text'>Bringing Gmail Muzzle out of retirement</title><content type='html'>&lt;p&gt;I really liked the Gmail Labs "Muzzle" feature, which hides the status messages of contacts in the Gmail chat list. Unfortunately, Google &lt;a href="http://gmailblog.blogspot.com/2010/02/gmail-labs-graduation-and-retirement.html"&gt;retired&lt;/a&gt; this lab last week.&lt;/p&gt;
&lt;p&gt;Happily, Yojimbow has replicated the functionality of Muzzle in &lt;a href="http://userscripts.org/scripts/show/69881"&gt;a Greasemonkey script&lt;/a&gt;. (The script is &lt;a href="http://userscripts.org/scripts/review/69881"&gt;only 8 lines long&lt;/a&gt;, with just 2 lines of Javascript! A very elegant solution.)&lt;/p&gt;
&lt;p&gt;Firefox users can install Greasemonkey, and then install this user script; meanwhile, Google Chrome natively understands user scripts (making them look like extensions), and you can just click on links to them to install.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2928460614973917844?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2928460614973917844/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/03/bringing-gmail-muzzle-out-of-retirement.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2928460614973917844'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2928460614973917844'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/03/bringing-gmail-muzzle-out-of-retirement.html' title='Bringing Gmail Muzzle out of retirement'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-3797920453165419589</id><published>2010-02-28T23:58:00.000-08:00</published><updated>2010-03-01T00:01:16.791-08:00</updated><title type='text'>2009 in Review (belated)</title><content type='html'>&lt;p&gt;Well, better late than never, I suppose.&lt;/p&gt;

&lt;p&gt;Things in software/computing that were new for me last year:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;I started writing &lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt;, at first just to scratch an itch. I was surprised by the response to it.&lt;/li&gt;
  &lt;li&gt;My day job is now mostly writing Java. I'm more comfortable with more dynamic languages but there are quite a few things I like about Java. More about this later.&lt;/li&gt;
  &lt;li&gt;Switched to Google Chrome. It's blazing fast.&lt;/li&gt;
  &lt;li&gt;Started using Google Wave for a few things. It's still in a state of &lt;em&gt;major&lt;/em&gt; flux and a lot of issues are still being ironed out, but I really like it. No other discussion tool I've ever used matches Wave in immediacy while scaling up to support readable and usable conversations that contain up to hundreds of contributors. In many scenarios I think having people on a Wave can make them more productive than if you could put them in a room together.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These were the most popular blog posts I wrote last year:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2009/02/configuring-radeon-r600r700-devices-on.html"&gt;Configuring Radeon r600/r700 devices on Ubuntu Jaunty&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2009/01/ubuntu-netboot-installers.html"&gt;The Ubuntu netboot/network installers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2009/06/making-your-own-page-day-calendar.html"&gt;Making your own page a day calendar&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2009/05/making-gorgeous-latex-plots-with-octave.html"&gt;Making gorgeous LaTeX plots with Octave&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2009/01/disabling-firefoxs-yellow-plugin-bar.html"&gt;Disabling Firefox's yellow plugin bar&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2009/08/auctex-and-preview-latex.html"&gt;AUCTeX and preview-latex&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And these were the most visited blog posts that were written in previous years:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2008/09/scrolling-with-thinkpads-trackpoint-in.html"&gt;Scrolling with the Thinkpad's TrackPoint in Ubuntu&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2008/03/emacs-in-ubuntu-hardy-now-has-anti.html"&gt;Emacs in Ubuntu Hardy now has anti-aliased fonts&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2008/06/using-wget-or-curl-to-download-web.html"&gt;Using wget or curl to download web sites for archival&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2007/12/for-else-in-python.html"&gt;&lt;tt&gt;for...else&lt;/tt&gt; in Python&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2007/11/version-control-with-git-remote.html"&gt;Git and remote repositories&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2007/12/version-control-with-git-git-add.html"&gt;&lt;tt&gt;git add --interactive&lt;/tt&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-3797920453165419589?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/3797920453165419589/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/02/2009-in-review-belated.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/3797920453165419589'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/3797920453165419589'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/02/2009-in-review-belated.html' title='2009 in Review (belated)'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5566488932180920665</id><published>2010-01-31T18:56:00.000-08:00</published><updated>2010-01-31T18:57:01.693-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>"Edit with Emacs" Chrome extension</title><content type='html'>&lt;p&gt;&lt;a href="http://www.bennee.com/~alex/"&gt;Alex Benn&amp;eacute;e&lt;/a&gt; has written an &lt;a href="https://chrome.google.com/extensions/detail/ljobjlafonikaiipfkggjbhkghgicgoh"&gt;Edit with Emacs&lt;/a&gt; extension for Google Chrome. It's Chrome's answer to Firefox's "It's all text" extension, which makes composing emails, blog posts, and other long-form text in a browser a lot more tolerable. (Hooray!)&lt;/p&gt;
&lt;p&gt;Since Chrome extensions can't spawn arbitrary processes, the Edit with Emacs extension requires the cooperation of an additional &lt;em&gt;edit server&lt;/em&gt; that can. The edit server is implemented in elisp and is bundled with the extension.&lt;/p&gt;
&lt;p&gt;Installation instructions:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Visit the &lt;a href="https://chrome.google.com/extensions/detail/ljobjlafonikaiipfkggjbhkghgicgoh"&gt;extension gallery page&lt;/a&gt; and click "Install".&lt;/li&gt;
  &lt;li&gt;In Chrome, click on the wrench menu, Extensions, "Options" under "Edit with Emacs", and follow the instructions there for setting up the edit server.&lt;/li&gt;
  &lt;li&gt;After configuring the edit server, click "Test Edit Server" to make sure everything is working.&lt;/li&gt;
  &lt;li&gt;Henceforth, in any new tabs you open, you'll see a little "edit" button next to any &lt;tt&gt;textarea&lt;/tt&gt; elements, which you can click on to pop up a new editor frame. (You can also double-click on the &lt;tt&gt;textarea&lt;/tt&gt;.)&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5566488932180920665?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5566488932180920665/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/01/edit-with-emacs-chrome-extension.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5566488932180920665'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5566488932180920665'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/01/edit-with-emacs-chrome-extension.html' title='&quot;Edit with Emacs&quot; Chrome extension'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4123153333894445751</id><published>2010-01-27T01:11:00.000-08:00</published><updated>2010-09-29T22:05:25.951-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Firefox 3.6</title><content type='html'>&lt;p&gt;Mozilla released Firefox 3.6 last week. There are many noticeable improvements compared to Firefox 3.5, but two that stand out to me.&lt;/p&gt;
&lt;p&gt;First, performance has improved quite a bit. And not just Javascript performance. Startup time is improved; the awesomebar responds instantly to keystrokes; Javascript and redraw/redisplay are faster. I no longer perceive a huge speed difference between Firefox and Google Chrome on most web apps, and the UI has become more responsive. (A few things&amp;mdash;startup time, redraw/redisplay/scrolling, and creating/closing new windows and tabs&amp;mdash;are still minorly annoying when I use Firefox alongside Chrome&amp;mdash;but 3.5 and 3.6 are like night and day.)&lt;/p&gt;
&lt;p&gt;Second, Firefox 3.6's implementation of HTML5 media, or at least audio, is superb. Having spent lots of time hacking on and listening to &lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt; on Chrome, Firefox 3.5, and Firefox 3.6, the latter is the one where things most often just seem to work as spec'd. Moreover it's Firefox 3.6 (and only Firefox 3.6) that can consistently maintain the illusion that I'm using a native media player rather than a web-based one. That's colossal.&lt;/p&gt;
&lt;p&gt;So, kudos to the Firefox developers.&lt;/p&gt;
&lt;p&gt;PSA: the &lt;a href="https://launchpad.net/~ubuntu-mozilla-daily/+archive/ppa"&gt;ubuntu-mozilla-daily&lt;/a&gt; PPA has nightly builds of Firefox 3.5, 3.6, and 3.7 packaged for all Ubuntu releases since Hardy. It's a low-hassle way to teach an old dog new tricks.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4123153333894445751?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4123153333894445751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/01/firefox-36.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4123153333894445751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4123153333894445751'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/01/firefox-36.html' title='Firefox 3.6'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-1363365521312516766</id><published>2010-01-25T19:22:00.000-08:00</published><updated>2010-09-30T11:59:50.298-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Python'/><title type='text'>Two Python curiosities</title><content type='html'>&lt;p&gt;I learn something new every day.&lt;/p&gt;
&lt;p&gt;First, the sort of thing you could do to mess with someone when they step away from their Python interactive shell to go use the restroom:&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; False = True
&amp;gt;&amp;gt;&amp;gt; False
True
&amp;gt;&amp;gt;&amp;gt; if False: print "Woo!"
... 
Woo!&lt;/pre&gt;
&lt;p&gt;Sure enough, &lt;tt&gt;True&lt;/tt&gt; and &lt;tt&gt;False&lt;/tt&gt; are just names in the builtin namespace that can be rebound. This capability seems pretty dangerous, so I'd expect to see something like it in C or in Lisp, but its presence in Python surprised me a bit.&lt;/p&gt;
&lt;p&gt;Second, the following puzzle stumped me for a while when I first saw it. Why does the following expression evaluate as it does?&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; "string" in [] == False
False&lt;/pre&gt;
&lt;p&gt;It's not a precedence issue, because that result is not consistent with &lt;em&gt;either&lt;/em&gt; of the parenthesizations:&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt;&amp;gt; ("string" in []) == False
True
&amp;gt;&amp;gt;&amp;gt; "string" in ([] == False)
Traceback (most recent call last):
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;
TypeError: argument of type 'bool' is not iterable&lt;/pre&gt;
&lt;p&gt;It's actually a consequence of &lt;a href="http://docs.python.org/reference/expressions.html#notin"&gt;Python's support for chained comparison operators&lt;/a&gt;. That is, just as&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;5 &amp;lt; a &amp;lt;= 7&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;desugars to&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;5 &amp;lt; a and a &amp;lt;= 7&lt;/tt&gt;,&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;the first expression above desugars to &lt;tt&gt;"string"&amp;nbsp;in&amp;nbsp;[]&amp;nbsp;and&amp;nbsp;[]&amp;nbsp;==&amp;nbsp;False&lt;/tt&gt;, which is &lt;tt&gt;False&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;It's good that the comparison operators (&lt;tt&gt;&amp;lt; &amp;lt;= &amp;gt; &amp;gt;= == != in is&lt;/tt&gt;) work in this consistent way, but it can trip up Python novices who have not yet learned that they really &lt;em&gt;have&lt;/em&gt; to write the more Pythonic expression &lt;tt&gt;"string"&amp;nbsp;not&amp;nbsp;in&amp;nbsp;[]&lt;/tt&gt; if they want to stay out of trouble.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-1363365521312516766?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/1363365521312516766/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/01/two-python-curiosities.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1363365521312516766'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1363365521312516766'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/01/two-python-curiosities.html' title='Two Python curiosities'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7520204388868746754</id><published>2010-01-24T00:52:00.000-08:00</published><updated>2010-01-24T00:53:11.297-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zeya'/><title type='text'>Zeya 0.4</title><content type='html'>&lt;p&gt;I'm pleased to announce the 0.4 release of &lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt;. Zeya is a web server that lets you listen to your music collection, from anywhere, using nothing more than Firefox or Google Chrome.&lt;/p&gt;
&lt;p&gt;Major changes since Zeya 0.3:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Gapless playback. This feature works with varying degrees of success on various browsers; I recommend Firefox 3.6. Firefox 3.6 &amp;gt; Google Chrome 4.x &amp;gt; Firefox 3.5.&lt;/li&gt;
  &lt;li&gt;"Shuffle" feature. (Thanks to &lt;a href="http://amitksaha.wordpress.com/"&gt;Amit Saha&lt;/a&gt;)&lt;/li&gt;
  &lt;li&gt;"Repeat playlist" feature.&lt;/li&gt;
  &lt;li&gt;New &lt;tt&gt;playlist&lt;/tt&gt; backend, which serves all the songs specified in an M3U playlist. (Amit Saha)&lt;/li&gt;
  &lt;li&gt;A sample Upstart script, which shows how to run Zeya at startup on Upstart-based systems, such as Ubuntu 9.10/Karmic and later. (Amit Saha)&lt;/li&gt;
  &lt;li&gt;Turned on traffic shaping for Google Chrome clients, so streaming doesn't hose low-bandwidth connections.&lt;/li&gt;
  &lt;li&gt;Other bug fixes and improvements to the listening experience.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Zeya has also now been packaged for Ubuntu! (More precisely, the Debian package has been synced to Ubuntu Lucid.) On Debian testing or unstable and Ubuntu 10.04/Lucid, install the &lt;tt&gt;zeya&lt;/tt&gt; package:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;# apt-get install zeya&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;(It may be several more days before 0.4 appears in Debian testing or Ubuntu.)&lt;/p&gt;
&lt;p&gt;See &lt;a href="http://web.psung.name/zeya/"&gt;&lt;tt&gt;http://web.psung.name/zeya/&lt;/tt&gt;&lt;/a&gt; for more information about Zeya, installation, getting started, reporting bugs, and development.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7520204388868746754?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7520204388868746754/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/01/zeya-04.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7520204388868746754'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7520204388868746754'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/01/zeya-04.html' title='Zeya 0.4'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5411984844325590790</id><published>2010-01-17T11:39:00.000-08:00</published><updated>2010-01-17T11:39:00.362-08:00</updated><title type='text'>Charitable donations</title><content type='html'>&lt;p&gt;I donated to the following charities and organizations in the past year (although I really meant to get this post out before the end of 2009):&lt;/p&gt;
&lt;p&gt;&lt;a href="https://secure.unicefusa.org/site/Donation2?df_id=6680&amp;6680.donation=form1"&gt;UNICEF&lt;/a&gt;, to support relief operations following the earthquake in Haiti.&lt;/p&gt;
&lt;p&gt;The &lt;a href="https://my.fsf.org/associate/support_freedom?referrer=6025"&gt;Free Software Foundation&lt;/a&gt;, which has a simple but lofty goal: to ensure that the computers we use and carry around with us every day are actually &lt;em&gt;accountable&lt;/em&gt; to us. Their public awareness efforts are invaluable, but if they did nothing but maintain the GNU operating system (including, ahem, Emacs), I would still be thankful beyond measure.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://wikimediafoundation.org/wiki/Appeal/en"&gt;Wikipedia&lt;/a&gt;, for being one of the things that makes the web so wonderful.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://support.creativecommons.org/donate"&gt;Creative Commons&lt;/a&gt;, for showing that we can do better than "All rights reserved."&lt;/p&gt;
&lt;p&gt;&lt;a href="https://giving.mit.edu/givenow/ocw/MakeGift.dyn"&gt;MIT Open CourseWare&lt;/a&gt;, for disseminating knowledge. OCW relies on donations to keep the lights on and to fund digitization of more classes.&lt;/p&gt;
&lt;p&gt;My local branch of &lt;a href="http://feedingamerica.org/"&gt;Feeding America&lt;/a&gt; (aka Second Harvest Food Bank). There is something depraved about hunger in the midst of plenty, and so close to home.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.amnestyusa.org/index.html"&gt;Amnesty International&lt;/a&gt;, that everyone may have the basic human dignities that you and I enjoy.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5411984844325590790?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5411984844325590790/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2010/01/charitable-donations.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5411984844325590790'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5411984844325590790'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2010/01/charitable-donations.html' title='Charitable donations'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2747937296184625897</id><published>2009-12-26T15:45:00.000-08:00</published><updated>2010-09-07T01:03:08.234-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Subtleties of search-and-replace in Emacs</title><content type='html'>&lt;p&gt;The search/replace mechanism in Emacs is a beautiful thing, full of subtleties.&lt;/p&gt;
&lt;p&gt;It is pretty clear that its design has been honed to an edge by about 20 years of heavy use. You might not think there could be much to it, but a lot of apps that have come along since then could learn something from some of its features:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Incremental search.&lt;/b&gt; (isearch, or "find as you type") This has gained traction elsewhere in recent years. To search, press &lt;tt&gt;C-s&lt;/tt&gt; and start typing; &lt;tt&gt;C-s&lt;/tt&gt; again takes you to successive matches. Emacs highlights all the matches that are visible:&lt;/p&gt;
&lt;p&gt;&lt;img style="border: 0" src="http://lh4.ggpht.com/_egN-3IJO0Xg/SzafweSYfUI/AAAAAAAADNE/uLwT0ojZmu4/1.png"&gt;&lt;/p&gt;
&lt;p&gt;You can save quite a bit of typing this way because you can stop as soon as you've typed a prefix that uniquely identifies the text you're looking for.&lt;/p&gt; &lt;p&gt;In addition, the search UI is in the minibuffer, instead of in a separate dialog that covers part of your document.&lt;/p&gt;
&lt;p&gt;Firefox, Chrome, and gedit all have fairly similar features; however, they only expose bare-bones search functionality through them. OpenOffice and most word processors bring up a big and jarring dialog.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Yanking from the document.&lt;/b&gt; This is like auto-completion for your searches. Suppose you're looking for all instances of "&lt;tt&gt;tag.artist&lt;/tt&gt;" in your document. Press &lt;tt&gt;C-s&lt;/tt&gt; and start typing...&lt;/p&gt;
&lt;p&gt;&lt;img style="border: 0" style="border: 0" src="http://lh4.ggpht.com/_egN-3IJO0Xg/Szafwgjby_I/AAAAAAAADNI/IWuIXlZKRUc/7.png"&gt;&lt;/p&gt;
&lt;p&gt;Now you notice that the word following the highlighted match is exactly what you were looking for. Just press &lt;tt&gt;C-w&lt;/tt&gt; to pull the next word into your query:&lt;/p&gt;
&lt;p&gt;&lt;img style="border: 0" style="border: 0" src="http://lh4.ggpht.com/_egN-3IJO0Xg/SzafwqFrCWI/AAAAAAAADNM/pdbU2RLpe48/8.png"&gt;&lt;/p&gt;
&lt;p&gt;Then pressing &lt;tt&gt;C-s&lt;/tt&gt; searches for subsequent occurrences of &lt;tt&gt;tag.artist&lt;/tt&gt;. If you think this is useful, just think about how awesome it is when you need to search for &lt;tt&gt;superLongIdentifierNames&lt;/tt&gt; in Java code.&lt;/p&gt;
&lt;p&gt;You can also yank just the next character from the document, or everything up to the end of the line. Type &lt;tt&gt;C-h k C-s&lt;/tt&gt; in Emacs to learn more.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Case replacement.&lt;/b&gt; If you have the text &lt;blockquote&gt;&lt;pre&gt;Eat &lt;span style="color: #060"&gt;foo&lt;/span&gt; for breakfast!
&lt;span style="color: #060"&gt;Foo&lt;/span&gt; is the best medicine.
VOTE &lt;span style="color: #060"&gt;FOO&lt;/span&gt; FOR PRESIDENT&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;and replace (&lt;tt&gt;M-x query-replace&lt;/tt&gt; or &lt;tt&gt;M-%&lt;/tt&gt;) "&lt;tt&gt;foo&lt;/tt&gt;" with "&lt;tt&gt;bar&lt;/tt&gt;", what do you get? Exactly what you expect:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;Eat &lt;span style="color: #060"&gt;bar&lt;/span&gt; for breakfast!
&lt;span style="color: #060"&gt;Bar&lt;/span&gt; is the best medicine.
VOTE &lt;span style="color: #060"&gt;BAR&lt;/span&gt; FOR PRESIDENT&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;This is clearly what you want most of the time, at least when you're editing prose. Gedit and OpenOffice don't do this (and Chrome and Firefox don't have a "replace" feature).&lt;/p&gt;
&lt;p&gt;(What happens, you ask, if you're editing code, or anything else where case sensitivity is critical? Emacs's heuristic is to only turn on these smart replacements when your query and replacement text are both all lowercase. You can also manually toggle case-sensitivity in searching with &lt;tt&gt;M-c&lt;/tt&gt;. For what it's worth, I've never noticed a false positive when editing code.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Cycling behavior.&lt;/b&gt; Many programs do a poor job of letting you know when your search has wrapped around to the beginning of the document. In Firefox, I often find that I can inadvertently cycle through looking at all the search results two or three times before I realize what I've done.&lt;/p&gt;
&lt;p&gt;After the last match in a document, Gedit and Chrome wrap around to the beginning silently. Firefox wraps around and concurrently displays a notification in the search UI. The problem is that if your attention is focused on the document &lt;em&gt;content&lt;/em&gt;&amp;mdash;as it probably is if you're scanning the individual matches&amp;mdash;it's easy to miss the cues that tell you the search has wrapped around (e.g. Firefox's notification, or the scroll bar jumping back). You can end up back at the beginning of the document without realizing it.&lt;/p&gt;
&lt;p&gt;At the other end of the spectrum, OpenOffice brings up a big and jarring dialog asking you "Yes/No" whether you want to continue searching at the beginning. Not so great, either.&lt;/p&gt;
&lt;p&gt;How does Emacs deal with this? When you've reached the last match for a query in the buffer, pressing &lt;tt&gt;C-s&lt;/tt&gt; &lt;em&gt;does nothing&lt;/em&gt;, except raising a quiet notification that there are no remaining matches:&lt;/p&gt;
&lt;p&gt;&lt;img style="border: 0" style="border: 0" src="http://lh4.ggpht.com/_egN-3IJO0Xg/Szafw0vKYbI/AAAAAAAADNQ/6bey7wCbtnw/6.png"&gt;&lt;/p&gt;
&lt;p&gt;If you press &lt;tt&gt;C-s&lt;/tt&gt; again, however, the search wraps back around to the beginning of the buffer.&lt;/p&gt;
&lt;p&gt;That is, at the last match, &lt;tt&gt;C-s&lt;/tt&gt; is &lt;em&gt;not&lt;/em&gt; initially met with an immediate jump to a new match (as it usually is); Emacs gives just enough "pushback" to ensure that the user is aware when the search has wrapped, even if they're &lt;em&gt;not paying any attention&lt;/em&gt; to the application chrome (minibuffer and scroll bars)! Very cool.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Displaying failed searches.&lt;/b&gt; When you type something that doesn't have a match, Emacs brings you to the maximal matching prefix of whatever you typed, and highlights the part of your query that wasn't found:&lt;/p&gt;
&lt;p&gt;&lt;img style="border: 0" style="border: 0" src="http://lh4.ggpht.com/_egN-3IJO0Xg/Szafw3Iq9eI/AAAAAAAADNU/Zfko406wCCs/5.png"&gt;&lt;/p&gt;
&lt;p&gt;This kind of feedback gives you a good idea of whether or not you made a typo/error in your search: if you did, it often appears near the point where the text stopped matching.&lt;/p&gt;
&lt;p&gt;If you only get all-or-nothing feedback telling you "no matches were found," then you are sort of groping around in the dark as you try to figure out what went wrong.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Search as a method for navigation.&lt;/b&gt; Perhaps the killer feature of isearch in Emacs is that you can use it as the primary method for moving around in a document, essentially replacing most of the functions of the PgUp/PgDn keys and the scroll bar in other applications.&lt;/p&gt;
&lt;p&gt;Part of this has to do with the fact that the search UI is so lightweight (no dialog boxes!). However, isearch in Emacs is also cool because it facilitates many use cases:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;During a search, you can press &lt;tt&gt;C-g&lt;/tt&gt; to cancel and return to where you started. This is handy if you just wanted to search for something in order to get a quick glance at it.&lt;/li&gt;
  &lt;li&gt;&amp;hellip;However, if you do indeed want to stop at the current match, press &lt;tt&gt;RET&lt;/tt&gt;. Perhaps you want to make some quick edits or do some more extensive reading at that spot. But when you're done with that, you can press &lt;tt&gt;C-x C-x&lt;/tt&gt; to return to where you originally were, because Emacs has set the mark to the place where you started.&lt;/li&gt;
  &lt;li&gt;&amp;hellip;Or, you can just continue editing there with no intention of returning to your original position.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Gedit and OpenOffice really only support that very last use case. You can hold your existing spot in a document with the cursor, but then you're limited to looking around with the scrollbars, which is cumbersome. Or you can use the Find feature or otherwise move the cursor, but then you've lost your original position.&lt;/p&gt;
&lt;p&gt;Emacs is like your very own personal assistant: it remembers things so you don't have to.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I haven't mentioned many of the miscellaneous keyboard-accessible commands and options available from within isearch and &lt;tt&gt;query-replace&lt;/tt&gt;. These are well worth your time to learn, although they are quite self-explanatory if you read the integrated help:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;For options available in isearch, type &lt;tt&gt;C-h k C-s&lt;/tt&gt;.&lt;/li&gt;
  &lt;li&gt;For options available in &lt;tt&gt;query-replace&lt;/tt&gt;, type &lt;tt&gt;C-h&lt;/tt&gt; at a &lt;tt&gt;query-replace&lt;/tt&gt; prompt.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I'd sum up some of the more generalizable design principles behind search-and-replace in Emacs as follows:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Reduce extraneous typing.&lt;/li&gt;
  &lt;li&gt;Stay out of the user's way whenever possible.&lt;/li&gt;
  &lt;li&gt;However, alert the user with immediate and useful feedback whenever necessary.&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2747937296184625897?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2747937296184625897/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/12/subtleties-of-search-and-replace-in.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2747937296184625897'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2747937296184625897'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/12/subtleties-of-search-and-replace-in.html' title='Subtleties of search-and-replace in Emacs'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_egN-3IJO0Xg/SzafweSYfUI/AAAAAAAADNE/uLwT0ojZmu4/s72-c/1.png' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7257674604023262922</id><published>2009-12-20T00:34:00.000-08:00</published><updated>2010-09-29T22:06:52.514-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Manipulating Picasa Web Albums programmatically</title><content type='html'>&lt;p&gt;I was pleased to find out that the &lt;a href="http://code.google.com/apis/picasaweb/docs/1.0/developers_guide_python.html"&gt;&lt;b&gt;Picasa Web Albums API&lt;/b&gt;&lt;/a&gt; makes it quite easy to programmatically upload and download photos from &lt;a href="http://picasaweb.google.com/"&gt;Picasaweb&lt;/a&gt;. So any desktop app that manipulates photos or graphics can easily be extended so that it can interact with web albums. The possibilities are manifold&amp;hellip; below is some code that demonstrates a couple of the basic capabilities.&lt;/p&gt;
&lt;p&gt;Like everything else on Ubuntu/Debian, you only need about 15 seconds to obtain all you need to get started with this. Just install the &lt;tt&gt;&lt;b&gt;python-gdata&lt;/b&gt;&lt;/tt&gt; package:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;$ sudo aptitude install python-gdata&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;b&gt;Uploading albums to Picasaweb&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;The following function creates a new Picasaweb album from a sequence of photos and associated captions.&lt;/p&gt;
&lt;div style="border: 1px solid #bbb; padding: 0.5em; background-color: #f8f8f8"&gt;&lt;pre&gt;#!/usr/bin/python
import gdata.photos.service
import os.path

def create_new_album(album_title, email, password, photos):
    """
    &lt;b&gt;Creates a new Picasa Web Album with the specified images.&lt;/b&gt;

    album_title: title of album, e.g. "Spring Break 2009"
    email: Google account name, e.g. yourname@gmail.com
    password: Google account password
    photos: sequence of tuples where each entry is (filename, caption)
            e.g. [("/tmp/photo0001.jpg", "A huge turtle"), ...]
    """
    &lt;b&gt;# Authenticate to Picasa Web Albums.&lt;/b&gt;
    gd_client = gdata.photos.service.PhotosService()
    gd_client.email = email
    gd_client.password = password
    gd_client.source = 'MyPhotoUploader' &lt;b&gt;# Fill in the name of your program here.&lt;/b&gt;
    gd_client.ProgrammaticLogin()

    &lt;b&gt;# Create the album.&lt;/b&gt;
    album = gd_client.InsertAlbum(title = album_title, summary = '')
    album_url = '/data/feed/api/user/%s/albumid/%s' % \
        (album.user.text, album.gphoto_id.text)

    &lt;b&gt;# Insert the photos.&lt;/b&gt;
    for filename, caption in file_info:
        gd_client.InsertPhotoSimple(
            album_or_uri=album_url,
            title=os.path.basename(filename), &lt;b&gt;# This shows up as 'Filename' on Picasaweb&lt;/b&gt;
            summary=caption,
            filename_or_handle=filename,
            content_type="image/jpeg")&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;b&gt;Downloading albums from Picasaweb&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Normally you can't download entire albums directly from the web (unless you have the Picasa client software installed). You can however use the API for this purpose (the parts in blue below are the core, non-interactive part of the program):&lt;/p&gt;
&lt;div style="border: 1px solid #bbb; padding: 0.5em; background-color: #f8f8f8"&gt;&lt;pre&gt;#!/usr/bin/python
#
# This interactive script prompts the user for an album to download.

import gdata.photos.service
import urllib

def main():
    &lt;b&gt;"Downloads a Picasa Web Album of the user's choice to the current directory."&lt;/b&gt;
    gd_client = gdata.photos.service.PhotosService()
    username = raw_input("Username? ")            # Prompt for a Google account username.
    print_album_names(gd_client, username)        # Enumerate the albums owned by that account.
    album_id = raw_input("Album ID? ")            # Prompt for an album ID.
    download_album(gd_client, username, album_id) # Download the corresponding album!

def print_album_names(gd_client, username):
    "Enumerates the albums owned by USERNAME."
    albums = gd_client.GetUserFeed(user = username)
    for album in albums.entry:
        print '%-30s (%3d photos) id = %s' % \
            (album.title.text, int(album.numphotos.text), album.gphoto_id.text)

&lt;span style="color: #009"&gt;def download_album(gd_client, username, album_id):
    &lt;b&gt;"Downloads all the photos in the album ALBUM_ID owned by USERNAME."&lt;/b&gt;
    photos = gd_client.GetFeed('/data/feed/api/user/%s/albumid/%s?kind=photo'
                               % (username, album_id))
    for photo in photos.entry:
        download_file(photo.content.src)

def download_file(url):
    "Download the data at URL to the current directory."
    basename = url[url.rindex('/') + 1:]  # Figure out a good name for the downloaded file.
    print "Downloading %s" % (basename,)
    urllib.urlretrieve(url, basename)&lt;/span&gt;

if __name__ == '__main__':
    main()&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;b&gt;More info&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://code.google.com/apis/picasaweb/docs/1.0/developers_guide_python.html"&gt;Picasaweb API developer's guide (Python client)&lt;/a&gt;. From that page you can also find more about bindings for .NET, Java, and PHP.&lt;/p&gt;
&lt;p&gt;I hereby release the code in this post into the public domain.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7257674604023262922?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7257674604023262922/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/12/manipulating-picasa-web-albums.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7257674604023262922'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7257674604023262922'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/12/manipulating-picasa-web-albums.html' title='Manipulating Picasa Web Albums programmatically'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5089314077142476725</id><published>2009-11-30T21:22:00.000-08:00</published><updated>2009-11-30T22:49:42.340-08:00</updated><title type='text'>With a partner like Apple, who needs competitors?</title><content type='html'>&lt;p&gt;Apple's contempt for iPhone users and developers keeps pushing the limits of credulity. It is exemplified by its &lt;a href="http://www.apple.com/hotnews/apple-answers-fcc-questions/"&gt;response&lt;/a&gt; to the FCC inquiry into the Google Voice app:&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;FCC: Why did Apple reject the Google Voice application for iPhone and remove related third-party applications from its App Store?&lt;/p&gt; 
 &lt;p&gt;Apple: Contrary to published reports, Apple has not rejected the Google Voice application, and continues to study it. The application has not been approved because, as submitted for review, it appears to alter the iPhone's distinctive user experience by replacing the iPhone's core mobile telephone functionality and Apple user interface with its own user interface for telephone calls, text messaging and voicemail. Apple spent a lot of time and effort developing this distinct and innovative way to seamlessly deliver core functionality of the iPhone.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;At first glance what Apple has written doesn't even appear to be an answer to the question. Apple has, surprisingly, &lt;em&gt;not&lt;/em&gt; claimed that it's protecting users&amp;mdash;from harm, or from confusing apps. It only alludes to the fact that it has previously cited "duplicating existing functionality" (read: competing with Apple) as grounds for rejection.&lt;/p&gt;
&lt;p&gt;Now, it is Apple's platform to mold as they wish; if consumers get a gratis dialer app either way, what's the harm? Why would Apple object to third-party developers making the iPhone &lt;em&gt;better&lt;/em&gt;? Apple recognizes that it can't constrain them from subsequently bringing equivalent functionality to Android or WebOS or whatnot. What if there comes a day when the most commonly used apps (dialer, browser, etc.) have feature parity cross-platform? Who would buy an iPhone then? Many people, to be sure, just not quite as many as before.&lt;/p&gt;
&lt;p&gt;But instead of staying competitive by making great software, Apple is doing pretty much the opposite. It is trying to forestall competition the only way it knows how: by crippling the iPhone's software&amp;mdash;barring entire classes of applications&amp;mdash;to &lt;em&gt;obfuscate comparison&lt;/em&gt; between its products and competitors'. The result? There's a whole &lt;a href="http://apprejections.com/"&gt;world&lt;/a&gt; of apps now that the iPhone just won't run, to say nothing of the apps that never get written because development is such a crapshoot. Users have to pay the cost for Apple's decisions every day now.&lt;/p&gt;
&lt;p&gt;To add insult to injury, Apple is eager to remind everyone just how much "time and effort" its engineers spent on the iPhone's dialer. &lt;b&gt;Does Apple think so little of its users that it considers its own &lt;em&gt;good intentions&lt;/em&gt; justification enough to override users' requests?&lt;/b&gt; This isn't elementary school. You do not get points for "effort."&lt;/p&gt; 
&lt;p&gt;This madness is even codified in the iPhone SDK developer agreement. &lt;b&gt;Native apps are forbidden from carrying out instructions on behalf of users&lt;/b&gt; ("executable code" or "interpreted code"), [1] lest users actually get to choose what they want to do. From an engineering standpoint, code is everywhere&amp;mdash;web browsers, office programs, anything with macros, even &lt;em&gt;calculators&lt;/em&gt; all have "interpreted code" at the core of their functionality. It is striking that Apple actually &lt;em&gt;mandates&lt;/em&gt; that apps subvert their users instead of empowering them.&lt;/p&gt; 
&lt;p&gt;This situation is rather surreal.&lt;/p&gt;
&lt;p&gt;Apple does not even try to hide its contempt for its customers. The iPhone is a device that only allows choosing from a circumscribed set of carefully enumerated functions. Apple only thinly veils the fact that it despises third-party developers, who are ostensibly its "partners". If you develop for the iPhone, you have to deal with a company that believes it has more to gain from hindering you than from helping you.&lt;/p&gt;
&lt;p&gt;I am not suggesting that Apple's behavior is illegal, or even incomprehensible (the shareholders must love it)&amp;mdash;merely abhorrent. We choose the world we want to live in, and this is not something I want to be a part of, not when there are so many worthy alternatives.&lt;/p&gt; 
&lt;p&gt;Yet, Apple's candor is nothing if not refreshing. Most companies don't openly talk about the mechanics of their anti-competitive practices. They speak of protecting consumers from confusion, or keeping prices low. Not Apple. There is no dissembling here. Apple freely admits that it will do whatever it takes to keep competitors from getting a foothold, no matter the cost to its own customers. When we consider that fact, it seems that the App Store is not the opaque and inscrutable system that many have claimed it is. What Apple has done has been no more, and no less, than what it has said it would do.&lt;/p&gt;
&lt;blockquote style="font-size: smaller"&gt;
&lt;p&gt;[1] &lt;em&gt;3.3.2 An Application may not itself install or launch other executable code by any means[...]. No interpreted code may be downloaded and used in an Application except for code that is interpreted and run by Apple's Published APIs and built- in interpreter(s).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;You will have to see &lt;a href="http://wikileaks.org/wiki/Apple_iPhone_SDK_Agreement"&gt;Wikileaks&lt;/a&gt;(!) for the full agreement.&lt;/p&gt;
&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5089314077142476725?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5089314077142476725/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/11/with-partner-like-apple-who-needs.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5089314077142476725'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5089314077142476725'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/11/with-partner-like-apple-who-needs.html' title='With a partner like Apple, who needs competitors?'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5235126187547439040</id><published>2009-11-27T12:09:00.000-08:00</published><updated>2010-09-29T22:06:52.514-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ssh'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Modifying SSH port forwardings mid-session</title><content type='html'>&lt;p&gt;I frequently use SSH port forwarding to access services on computers I'm connected to (e.g. VNC, web servers, &lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt;). For example,&lt;/p&gt; 
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;ssh -L 8001:localhost:8080 foobar&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt; 
&lt;p&gt;connects port 8001 on my local machine to whatever service is running on &lt;tt&gt;foobar&lt;/tt&gt; port 8080.&lt;/p&gt; 
&lt;p&gt;Sometimes I'll discover mid-session that I wish to connect to a new service I've just started up remotely, or that I forgot to add the &lt;tt&gt;-L&lt;/tt&gt; flag for some service I wanted. I could always just disconnect, add the appropriate port forwardings, and reconnect.&lt;/p&gt; 
&lt;p&gt;However, I just learned that SSH also supports some &lt;em&gt;escape sequences&lt;/em&gt;, one of which lets you break out to a command line, where you can change port forwardings mid-session without disconnecting.&lt;/p&gt; 
&lt;p&gt;With the default settings, type &lt;tt&gt;&lt;b&gt;~C&lt;/b&gt;&lt;/tt&gt; at the beginning of your session or after a newline. You'll see a command prompt:&lt;/p&gt; 
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;ssh&amp;gt;&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt; 
&lt;p&gt;At this prompt, you can add additional forwardings using the same syntax that &lt;tt&gt;ssh&lt;/tt&gt; accepts:&lt;/p&gt; 
&lt;ul&gt; 
  &lt;li&gt;Local forwarding to remote service: &lt;tt&gt;-L local_port:hostname:hostport&lt;/tt&gt;&lt;/li&gt; 
  &lt;li&gt;Remote forwarding to local service: &lt;tt&gt;-R remote_port:hostname:hostport&lt;/tt&gt;&lt;/li&gt; 
  &lt;li&gt;Dynamic forwarding, e.g. for SOCKS: &lt;tt&gt;-D port&lt;/tt&gt;&lt;/li&gt; 
&lt;/ul&gt; 
&lt;p&gt;Further reading:&lt;/p&gt; 
&lt;ul&gt; 
  &lt;li&gt;&lt;a href="http://www.openbsd.org/cgi-bin/man.cgi?query=ssh#ESCAPE+CHARACTERS"&gt;More about escapes from the &lt;tt&gt;ssh&lt;/tt&gt; man page&lt;/a&gt;. (Escapes provide access to some nifty other features, too.)&lt;/li&gt; 
  &lt;li&gt;&lt;a href="http://psung.blogspot.com/2008/01/setting-up-reverse-ssh.html"&gt;Reverse SSH&lt;/a&gt; (Tricks for making port forwarding even more useful.)&lt;/li&gt; 
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5235126187547439040?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5235126187547439040/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/11/modifying-ssh-port-forwardings-mid.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5235126187547439040'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5235126187547439040'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/11/modifying-ssh-port-forwardings-mid.html' title='Modifying SSH port forwardings mid-session'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2616451884633712696</id><published>2009-11-19T23:29:00.000-08:00</published><updated>2010-09-29T22:06:52.515-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Assorted notes</title><content type='html'>&lt;p&gt;Many random notes (some for my own reference), each of which is too short to
  warrant a full blog post:&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Emacs&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;It had always bothered me, just a little, that &lt;tt&gt;C-v&lt;/tt&gt;
  and &lt;tt&gt;M-v&lt;/tt&gt;, in addition to scrolling, move the cursor to the bottom or
  top of the screen. This has the odd effect that &lt;tt&gt;C-v M-v&lt;/tt&gt; is not a
  no-op. Turns out that setting the variable
  &lt;tt&gt;scroll-preserve-screen-position&lt;/tt&gt; appropriately can fix this. (via
  &lt;a href="http://lists.gnu.org/archive/html/emacs-devel/2009-11/msg00288.html"&gt;emacs-devel&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Chrome&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Have you ever wondered why running Firefox instances get broken when new versions are installed? On GNU/Linux systems the package manager, which runs as root, pays no
    mind to what non-root users are doing. Some apps, like Firefox, run into
    major trouble because they'll load additional files after startup that can't be mixed and matched with the previous versions (this isn't really a problem for programs that are essentially just one binary). Chrome acquires immunity to this with
    its &lt;a href="http://code.google.com/p/chromium/wiki/LinuxZygote"&gt;Zygote
    mode&lt;/a&gt;, which basically means &lt;em&gt;do not load anything from disk after
    startup&lt;/em&gt;. A simple idea, but it takes some work to follow through with
    it.
  &lt;/li&gt;
  &lt;li&gt;
    Among visitors to this blog, Chrome is the second most popular browser,
    with a 9.5% share! Chrome leads IE (6.6%), Safari (5.9%), and Opera (4.3%),
    and trails only Firefox (72.6%). You can sort of see what a
    non-representative sample of web users happens across this blog.
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;Unix/Ubuntu&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href="http://soundconverter.berlios.de/"&gt;Soundconverter&lt;/a&gt;
      (&lt;tt&gt;aptitude install soundconverter&lt;/tt&gt;) is a handy GTK/GNOME program
      for converting (transcoding) audio between formats. It is easy to use,
      transfers all the music metadata, and seems to take full advantage of
      multicore processors. (I use it to downsample my music, mostly in FLAC,
      to Ogg or MP3 for use on portable devices.)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;When using &lt;tt&gt;find&lt;/tt&gt; with &lt;tt&gt;xargs&lt;/tt&gt;, &lt;tt&gt;xargs&lt;/tt&gt; will get
      tripped up by filenames with spaces (it will treat each space-delimited
      component as a different argument). You can get around this by changing
      the delimiter in both &lt;tt&gt;find&lt;/tt&gt; and &lt;tt&gt;xargs&lt;/tt&gt; to &lt;tt&gt;\0&lt;/tt&gt;
      instead of space, as follows:&lt;/p&gt;
    &lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;find . -iname '*.tmp' &lt;b&gt;-print0&lt;/b&gt; | xargs &lt;b&gt;-0&lt;/b&gt; rm&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
    &lt;p&gt;You can usually achieve the same effect with &lt;tt&gt;find ... -exec&lt;/tt&gt; but
      I can never remember how to use it.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;HTML, HTML5&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Some things I picked up while working
  on &lt;a href="http://web.psung.name/zeya"&gt;Zeya&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;p&gt;&lt;a href="http://www.webreference.com/programming/css_frames/index.html"&gt;
 Making a frame-like layout with CSS&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;a href="https://developer.mozilla.org/En/Using_audio_and_video_in_Firefox"&gt;HTML5
 audio/video APIs as implemented in Firefox&lt;/a&gt;. The audio/video APIs
 provide nearly all the features you'd need for a music player. Just add
 chrome!&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;&lt;a href="http://diveintohtml5.org/detect.html"&gt;Detecting HTML5
 features (from Dive Into HTML5)&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
  &lt;li&gt;&lt;p&gt;One cool feature in HTML5 that you may not have heard of (because it's
    not quite as earth-shattering as video, canvas, or local storage) is
      "placeholder text" for text boxes.&lt;/p&gt;
    &lt;p&gt;&lt;img style="height: 30px; width: 268px"
    src="http://c.wearehugh.com/dih5/location-bar-empty-unfocused.png"&gt;&lt;/p&gt;
    &lt;p&gt;(The text goes away when you focus the input and/or type something in
      it.)&lt;/p&gt;
    &lt;p&gt;It's a feature that (I assume, at least) people have been using
      Javascript hacks to implement for a long time.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2616451884633712696?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2616451884633712696/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/11/assorted-notes.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2616451884633712696'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2616451884633712696'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/11/assorted-notes.html' title='Assorted notes'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6576381724143042667</id><published>2009-11-16T20:05:00.000-08:00</published><updated>2010-07-18T22:28:48.842-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='computational research'/><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Git for researchers</title><content type='html'>&lt;p&gt;In my previous job—as a grad student, doing computational/biomedical research—I used Git to manage my projects.&lt;/p&gt;
&lt;p&gt;For small projects, people usually treat CVS/SVN as checkpointing tools—tools to get you back to a known good state when you've screwed up. Git, however, provides a whole new &lt;em&gt;vocabulary&lt;/em&gt; you can use to talk about creating, altering, composing, combining, splitting, undoing, and otherwise manipulating changes to code (commits). It helps you get stuff done faster every day, not just when you mess up.&lt;/p&gt;
&lt;p&gt;Here are a couple of reflections and "lessons learned" on really using VCS to your advantage in a research environment, where some of the rules of thumb are a bit different from those in industry.&lt;/p&gt;
&lt;p&gt;(They seem so stunningly obvious now that I've committed them to writing, but they seemed much less so when I first articulated them to myself.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Retaining history, all of it.&lt;/b&gt; I have found &lt;tt&gt;&lt;a href="http://www.kernel.org/pub/software/scm/git/docs/git-merge.html"&gt;git merge -s ours&lt;/a&gt;&lt;/tt&gt; to be very handy. It produces a merge commit and merge topology, tying in the history of the other branch, but without applying any of the changes produced in that branch.&lt;/p&gt;
&lt;p&gt;Typically, if a feature doesn't pan out, you delete the corresponding branch and destroy all evidence that you tried. But in exploratory or research contexts, the details of your failed experiments can be quite important. You might need to revisit some past state in order to perform further investigation. Or maybe you want to obtain some numbers for a paper or presentation.&lt;/p&gt;
&lt;p&gt;Graphically: &lt;span style="background-color:#dfc;"&gt;imagine you have a "successful" branch &lt;tt&gt;feature1&lt;/tt&gt; and a "failed" branch &lt;tt&gt;feature2&lt;/tt&gt;&lt;/span&gt; (left). You don't want to &lt;tt&gt;git branch -D feature2&lt;/tt&gt;, since that could cause its history to be lost. If you instead &lt;tt&gt;git merge -s ours feature2&lt;/tt&gt;, you get &lt;span style="background-color:#cdf;"&gt;a topology where the states from both branches appear in your &lt;tt&gt;git log&lt;/tt&gt;&lt;/span&gt; (right), but the state at the tip is the same as that at &lt;tt&gt;feature1&lt;/tt&gt;.&lt;/p&gt;

&lt;table&gt;&lt;tbody&gt;  &lt;tr&gt;    &lt;td valign="bottom" style="background-color: #dfc"&gt;
&lt;pre&gt;* ddddddd (refs/heads/feature1)
* ccccccc
* bbbbbbb
| * 2222222 (refs/heads/feature2)
| * 1111111
|/
* aaaaaaa&lt;/pre&gt;
   &lt;/td&gt;    &lt;td valign="bottom" style="background-color: #cdf"&gt;
&lt;pre&gt;* eeeeeee "Merge branch 'feature2'."
|\
* | ddddddd (refs/heads/feature1)
* | ccccccc
* | bbbbbbb
| * 2222222 (refs/heads/feature2)
| * 1111111
|/
* aaaaaaa&lt;/pre&gt;
   &lt;/td&gt;  &lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;

&lt;p&gt;This kind of setup makes tracking your progress &lt;em&gt;super easy&lt;/em&gt;. My &lt;tt&gt;git log&lt;/tt&gt; basically becomes the scaffolding for my research notebook. I have bare-bones notes like the following:&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;Commit &lt;tt&gt;2222222&lt;/tt&gt;: this change did not improve quality at all. Furthermore it runs much slower, probably because blah blah blah blah. See full output in &lt;tt&gt;/home/phil/logs/2222222&lt;/tt&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The great thing is that now &lt;em&gt;every&lt;/em&gt; result (whether a success or a failure) has, attached to it, a commit name: a pointer to the exact code that generated that result. If I hadn't had complete change history so easily available, I would have spent half of my time second-guessing results I'd already obtained.&lt;/p&gt;
&lt;p&gt;This application also demonstrates the strengths of &lt;acronym style="color: #060" title="distributed version control systems"&gt;DVCS&lt;/acronym&gt; versus &lt;acronym style="color: #060" title="centralized version control systems"&gt;CVCS&lt;/acronym&gt;. Research and software development do not happen in a clean linear way. There is lots of backtracking, and sometimes you cannot expect to work effectively with a VCS whose basic model is "one damn commit after another."&lt;/p&gt;
&lt;p&gt;Summary: 90% of everything ends in failure. Keeping your failure history (as well as your success history) around is something that is underemphasized.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Long-lived branches vs. refactoring&lt;/b&gt;. If you know what you're going to do in advance, then it's not called research. In my work, what I ended up writing on a day-to-day basis depended more on experimentation and testing than on planning and specs. Here's some sample code for illustrative purposes:&lt;/p&gt;
&lt;pre&gt;# (1)
def my_function(a, b):
   foo = &lt;b&gt;random_sample()&lt;/b&gt; # Random heuristic
   something(foo)
   ...&lt;/pre&gt;
&lt;p&gt;I want to find out how the following code stacks up against &lt;tt&gt;(1)&lt;/tt&gt;. Does it perform better? Is it faster?&lt;/p&gt;
&lt;pre&gt;# (2)
def my_function(a, b):
   foo = &lt;b&gt;shortest_path(a, b)&lt;/b&gt; # A better(?) heuristic
   something(foo)
   ...&lt;/pre&gt;
&lt;p&gt;In reality we might be evaluating alternative heuristics (as here), different numeric parameters, alternative algorithms, or an alternative data source (e.g., training vs. testing data).&lt;/p&gt;
&lt;p&gt;Sometimes, when there are a number of alternatives, the right thing to do is to refactor to parameterize the code, for example,&lt;/p&gt;
&lt;pre&gt;# (3)
def my_function(a, b, heuristic = 'shortest_path'):
   if heuristic == 'random':
       foo = random_sample()
   elif heuristic == 'shortest_path':
       foo = shortest_path(a, b)
   else:
       foo = ... # Additional logic...
   something(foo)
   ...&lt;/pre&gt;
&lt;p&gt;But every parameterization increases complexity. The new argument is something you have to think about every time you or someone else tries to read your code. Your function is longer, leaks more implementation details, and provides less abstraction. So you don't want to go down this route unless it's necessary. If one choice is a clear winner, and &lt;em&gt;every&lt;/em&gt; invocation is going to pass the same argument, then the extra generality you introduced is a liability, not an asset. To do that refactoring can be a lot of work without much reward.&lt;/p&gt;
&lt;p&gt;So you want to run and &lt;em&gt;evaluate&lt;/em&gt; the alternatives before refactoring. People who find themselves in this situation often write code like this:&lt;/p&gt;
&lt;pre&gt;# (4)
def my_function(a, b):
   foo = random_sample()
   ## Uncomment the next line if blah blah blah
   # foo = shortest_path(a, b)
   something(foo)
   ...&lt;/pre&gt;
&lt;p&gt;which is convenient to write, but setting all the switches by hand whenever you want to run it is rather error-prone, especially if the difference is more complicated than one line.&lt;/p&gt;
&lt;p&gt;Branching saves the day by letting your &lt;em&gt;tools&lt;/em&gt; manage what you were doing by hand in &lt;tt&gt;(4)&lt;/tt&gt;. You can compare alternatives like &lt;tt&gt;(1)&lt;/tt&gt; and &lt;tt&gt;(2)&lt;/tt&gt; above against each other if you keep them in parallel branches (granted, you can't select between the alternatives at runtime, but that may be OK). Maintenance  is a breeze: with &lt;tt&gt;git merge&lt;/tt&gt; it's easy to maintain multiple parallel source trees, differing by just that one line, for as long as you please. And because you're committing every merge commit, your results are 100% reproducible (if you were messing with your files by hand, in order to reproduce a code state you would have to not only specify a commit name, but also what lines you had commented and uncommented).&lt;/p&gt;
&lt;p&gt;After branching, you can mull it over and obtain data on all the alternatives. When you've made your decision, you either drop one implementation and end up with &lt;tt&gt;(1)&lt;/tt&gt; or &lt;tt&gt;(2)&lt;/tt&gt;, or, if you need the generality, &lt;em&gt;then&lt;/em&gt; you refactor so you can choose between them at runtime &lt;tt&gt;(3)&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Summary: lightweight branches allow you to &lt;em&gt;defer&lt;/em&gt; the work of refactoring rather than having to pay for it up front. They greatly improve the hackability of code, by letting you try out many different alternatives &lt;em&gt;reliably&lt;/em&gt; and without much hassle.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6576381724143042667?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6576381724143042667/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/11/git-for-researchers.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6576381724143042667'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6576381724143042667'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/11/git-for-researchers.html' title='Git for researchers'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5040344282400362416</id><published>2009-11-06T17:45:00.000-08:00</published><updated>2009-11-08T01:31:51.756-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zeya'/><title type='text'>Zeya 0.3</title><content type='html'>&lt;p&gt;I'm pleased to announce the 0.3 release of &lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt;. Zeya is a music player that runs in your (HTML5 draft standard-compliant) web browser, giving you streaming access to your music collection from pretty much anywhere.&lt;/p&gt;
&lt;p style="text-align: center"&gt;&lt;img style="border: 0; width: 629px; height: 250px" src="http://web.psung.name/zeya/images/zeya3-small.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://orebokech.com/"&gt;Romain Francoise&lt;/a&gt; has generously packaged Zeya for Debian. Debian "testing" (squeeze) users can now install Zeya as follows:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;# apt-get install zeya&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;(Zeya 0.2 is in Debian "testing" at present; Zeya 0.3 will be in "unstable" shortly and in "testing" after the requisite testing period.)&lt;/p&gt;
&lt;p&gt;Many significant changes have been made since Zeya 0.2:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You can filter your music collection by title, artist, or album with Zeya's new search functionality. (Thanks to &lt;a href="http://orebokech.com/"&gt;Romain Francoise&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Zeya implements traffic shaping for Firefox clients, to keep from hosing low-bandwidth network links.&lt;/li&gt;
&lt;li&gt;Zeya supports password protecting your music collection with Basic HTTP authentication, configurable with &lt;tt&gt;--basic_auth_file&lt;/tt&gt;. (Thanks to Samson Yeung)&lt;/li&gt;
&lt;li&gt;The default backend is now &lt;tt&gt;dir&lt;/tt&gt; (read all music within a directory) instead of &lt;tt&gt;rhythmbox&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;Initial load time is significantly improved, as Zeya now compresses output data when appropriate. This yields a 3-7x decrease in transfer size. (Romain Francoise)&lt;/li&gt;
&lt;li&gt;The target output bitrate can be set with &lt;tt&gt;--bitrate&lt;/tt&gt;. (Romain Francoise)&lt;/li&gt;
&lt;li&gt;Zeya does a better job of guessing reasonable metadata when the ID3 tags are missing. (Samson Yeung)&lt;/li&gt;
&lt;li&gt;Zeya listens on IPv6 interfaces by default. (Romain Francoise)&lt;/li&gt;
&lt;li&gt;Zeya is multithreaded for improved parallelism.&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;zeyaclient.py&lt;/tt&gt; supports skipping to the next song (with &lt;tt&gt;C-c&lt;/tt&gt;) and jumping back to the query prompt (with &lt;tt&gt;C-c C-c&lt;/tt&gt;).&lt;/li&gt;
&lt;li&gt;Zeya decodes MP3s using &lt;tt&gt;mpg123&lt;/tt&gt; instead of &lt;tt&gt;mpg321&lt;/tt&gt;, for some performance improvements.&lt;/li&gt;
&lt;li&gt;An online guide to the keyboard shortcuts has been added (click "Help" at the bottom or press &lt;tt&gt;?&lt;/tt&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many bug fixes and UI improvements have also been made.&lt;/p&gt;
&lt;p&gt;Known issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;tt&gt;zeyaclient&lt;/tt&gt; has not yet been updated to support basic HTTP authentication.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can obtain Zeya via git:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;git clone http://web.psung.name/git/zeya.git&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;As I mentioned above, Zeya is also packaged for Debian.&lt;/p&gt;
&lt;p&gt;See &lt;a href="http://web.psung.name/zeya/"&gt;&lt;tt&gt;http://web.psung.name/zeya/&lt;/tt&gt;&lt;/a&gt; for more information, including a &lt;a href="http://web.psung.name/zeya/install/"&gt;quick start guide&lt;/a&gt;. We'd appreciate hearing any problem reports on our new &lt;a href="https://bugs.launchpad.net/zeya"&gt;bug tracker&lt;/a&gt; or via Debian's bug tracker.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5040344282400362416?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5040344282400362416/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/11/zeya-03.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5040344282400362416'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5040344282400362416'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/11/zeya-03.html' title='Zeya 0.3'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6599374438870203804</id><published>2009-10-12T18:05:00.000-07:00</published><updated>2009-10-16T23:23:46.889-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zeya'/><title type='text'>Zeya 0.2</title><content type='html'>&lt;p&gt;&lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt; is a music server that streams your music collection to any computer, phone, television, picture frame, or refrigerator that has a current-generation web browser. The client part uses the &lt;tt&gt;&amp;lt;audio&amp;gt;&lt;/tt&gt; tag in the HTML5 draft spec, so it runs right in the browser&amp;mdash; without Flash or Silverlight and without the need to install any extra software at the client.&lt;/p&gt;
&lt;p&gt;I'm pleased to announce the 0.2 release of Zeya.&lt;/p&gt;
&lt;p style="text-align: center"&gt;&lt;a href="http://web.psung.name/zeya/zeya2.png"&gt;&lt;img src="http://web.psung.name/zeya/zeya2-cropped.png" style="width: 502px; height: 320px; background-color: #666; border: 2px solid #666"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;New since &lt;a href="http://psung.blogspot.com/2009/08/zeya-01.html"&gt;Zeya 0.1&lt;/a&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for Internet Explorer (via Google's &lt;a href="http://code.google.com/chrome/chromeframe/"&gt;Chrome Frame&lt;/a&gt; plugin). IE joins Firefox and Chrome in the list of supported browsers.&lt;/li&gt;
&lt;li&gt;A new console frontend (more below)&lt;/li&gt;
&lt;li&gt;Numerous UI improvements, both substantive and cosmetic&lt;/li&gt;
&lt;li&gt;A unit test suite&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are many bug fixes, the most notable being:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Filenames with non-ASCII characters can be read and served correctly.&lt;/li&gt;
&lt;li&gt;Files that are not in a decodable format are hidden entirely from the user.&lt;/li&gt;
&lt;li&gt;Zeya should actually work in Python 2.5 as advertised.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Known issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;64-bit GNU/Linux builds of the Google Chrome dev channel are undergoing some codec turbulence. Use either the 64-bit &lt;a href="https://launchpad.net/~chromium-daily/+archive/ppa"&gt;Chromium builds&lt;/a&gt; or 32-bit builds of Chrome or Chromium instead.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The new console frontend, &lt;tt&gt;zeyaclient.py&lt;/tt&gt;, is a simple (read: primitive) app that connects to a Zeya server and prompts for songs to play. This is handy if you are using a computer that doesn't have a supported web browser (but on which you can run Python scripts). The Sugar OS on the &lt;a href="http://wiki.laptop.org/go/XO"&gt;XO-1&lt;/a&gt; is one such setup, so I'm now using my XO, which is connected to a hi-fi set, as a jukebox for my living room.&lt;/p&gt;
&lt;p&gt;I've also been using Zeya more frequently to listen to music (from my home computer) at work. It's much more satisfying than internet radio.&lt;/p&gt;
&lt;p&gt;Visit &lt;tt&gt;&lt;a href="http://web.psung.name/zeya/"&gt;http://web.psung.name/zeya/&lt;/a&gt;&lt;/tt&gt; for more information, or read &lt;a href="http://psung.blogspot.com/search/label/Zeya"&gt;previous blog posts on Zeya&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6599374438870203804?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6599374438870203804/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/10/zeya-02.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6599374438870203804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6599374438870203804'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/10/zeya-02.html' title='Zeya 0.2'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4394982340926681126</id><published>2009-09-23T01:00:00.000-07:00</published><updated>2009-09-28T00:27:50.981-07:00</updated><title type='text'>It's time for web developers to break out the champagne</title><content type='html'>&lt;p&gt;It is somewhat amusing to realize that Google is not playing the same game as the other browser vendors. Its &lt;em&gt;incentives&lt;/em&gt; are very different, and that makes all the difference. Google is not directly interested in increasing adoption of Chrome; it actually benefits from increased use of the web on &lt;em&gt;any&lt;/em&gt; browser. Sundar Pichai, the Google VP in charge of Chrome, &lt;a href="http://www.nytimes.com/2009/07/26/technology/companies/26mozilla.html"&gt;has said as much&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;"We were all very clear that if the outcome was that somehow Mozilla [Firefox] lost share to Google [Chrome], and everything else remained the same, internally, we would have been seen as having failed," Mr. Pichai says.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;So, journalists who are fixated on &lt;em&gt;market share&lt;/em&gt;, like &lt;a href="http://www.pcworld.com/article/172123/can_chrome_shake_up_the_browser_market.html"&gt;JR Raphael of PC World&lt;/a&gt; (not to pick on him), are missing the point:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Can Chrome Shake Up the Browser Market? ... As it stands now, Chrome holds about 3 percent of the global browsing market ... Google's hope ... is to double that share by next September&amp;mdash;then triple it by 2011.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Chrome has &lt;em&gt;already&lt;/em&gt; shaken up the browser market. In the year that Chrome has been out, speed has become one of the primary selling points for &lt;a href="http://www.mozilla.com/en-US/firefox/performance/"&gt;every&lt;/a&gt; &lt;a href="http://www.microsoft.com/windows/internet-explorer/get-the-facts/default.aspx"&gt;major&lt;/a&gt; &lt;a href="http://www.apple.com/safari/whats-new.html#performance"&gt;browser&lt;/a&gt;. The performance of every browser (and hence, every web app) has improved dramatically, and more improvements are in the pipeline. That fact&amp;mdash;not Chrome's who-even-cares percentage market share&amp;mdash;is the story of this year.&lt;/p&gt;
&lt;p&gt;And the folks at Google are probably pretty happy with that. If people use a fast browser and load more web pages and use more Google products and see more advertisements, who cares if it says "Firefox" or "Chrome" in the title bar? Google doesn't.&lt;/p&gt;
&lt;p&gt;Hell, who cares if it says "Internet Explorer"? Google doesn't. Which brings me to &lt;a href="http://blog.chromium.org/2009/09/introducing-google-chrome-frame.html"&gt;&lt;b&gt;Chrome Frame&lt;/b&gt;&lt;/a&gt;, a plugin that runs a Chrome renderer &lt;em&gt;in IE&lt;/em&gt;:&lt;/p&gt;
&lt;p style="text-align: center"&gt;&lt;a href="http://lh4.ggpht.com/_egN-3IJO0Xg/Srm8RiaEHZI/AAAAAAAAC8g/y1ACXQd1eJQ/chromeframe2.png"&gt;&lt;img src="http://lh4.ggpht.com/_egN-3IJO0Xg/Srm8RiaEHZI/AAAAAAAAC8g/y1ACXQd1eJQ/s640/chromeframe2.png" style="border: 0"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I wept tears of joy when I first saw this. For comparison, see &lt;a href="http://en.wikipedia.org/wiki/File:Acid3ie8rc1.png"&gt;IE8's native rendering of Acid3&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The Chrome renderer is activated on an opt-in basis from web developers, using a special META tag.&lt;/p&gt;
&lt;p&gt;It remains to be seen how all this will pan out, but this is a very clever move on Google's part. It changes the economics both for IT departments and for developers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Many if not most IE users are unwilling or unable to change their browser for legacy/lockdown reasons; I suspect that is the most important reason why Firefox, after all these years, is only at around &lt;a href="http://marketshare.hitslink.com/report.aspx?qprid=0"&gt;23%&lt;/a&gt; market share. It's not that IT departments are inherently against installing new software. They'd love to be able to deploy spiffy HTML5 apps too. But their hands are tied because they &lt;em&gt;must&lt;/em&gt; make sure existing apps keep working. Now that they can use HTML5 apps &lt;em&gt;without breaking any legacy apps&lt;/em&gt;, they may be a lot more open to deploying Chrome Frame than to changing browsers entirely.&lt;/li&gt;
&lt;li&gt;Installing a plugin is &lt;em&gt;a lot&lt;/em&gt; easier for end users than installing a new browser. In fact, it's a routine enough operation that I suspect many web developers will soon choose to take the Chrome Frame route rather than continue to expend time, money, blood, sweat, and tears working on hacks for native IE support. When users are presented with a dialog saying "In order to use This App You Really Want you must install the mumble mumble plugin," most of them will do it. (Flash has upwards of 90% market penetration!)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Because it was willing to sneak in the side door, ship as a plugin, and strip the chrome from Chrome, Google may be the first to have a real shot at bringing fast and standards-compliant browsing to a majority of web users.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4394982340926681126?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4394982340926681126/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/09/its-time-for-web-developers-to-break.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4394982340926681126'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4394982340926681126'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/09/its-time-for-web-developers-to-break.html' title='It&apos;s time for web developers to break out the champagne'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_egN-3IJO0Xg/Srm8RiaEHZI/AAAAAAAAC8g/y1ACXQd1eJQ/s72-c/chromeframe2.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-872017476010699553</id><published>2009-09-15T22:33:00.000-07:00</published><updated>2009-09-28T00:35:00.895-07:00</updated><title type='text'>New external Thinkpad keyboard</title><content type='html'>&lt;p&gt;I ordered one of the &lt;a href="http://lenovoblogs.com/designmatters/?p=2364"&gt;new external Thinkpad keyboards&lt;/a&gt; and have been using it for a few days now.&lt;/p&gt;
&lt;p style="text-align: center"&gt;
  &lt;img src="http://lh6.ggpht.com/_egN-3IJO0Xg/SrBm8z268jI/AAAAAAAACew/Hbbt0hzC-Xw/Think-KB-toe1.JPG" style="border: 0"&gt;
&lt;/p&gt;
&lt;p&gt;Specs in brief: USB, no touchpad, no numpad, feels exactly like a Thinkpad T400s keyboard, and the price is right ($60).&lt;/p&gt;
&lt;p&gt;For my own purposes, the design decisions that Lenovo made here are pretty much spot-on. This thing is fantastic; in particular:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;TrackPoint scrolling on my desktop machine! No exaggeration, this alone is worth the price. Scrolling any other way is just&amp;hellip; uncivilized. I look forward to using the mouse a lot less.&lt;/li&gt;
  &lt;li&gt;I was at first skeptical of Lenovo's decision to make a small keyboard, but I think it really turned out well:
    &lt;ol&gt;
      &lt;li&gt;It significantly reduces the distance I have to reach to press keys like PgUp, PgDn, and the arrow keys. Alas, there are still a bunch of apps that have the poor sense to bind commonly used commands to keys like Ctrl+PgDn. I'm looking at you, web browsers. (If you wish, &lt;a href="http://psung.blogspot.com/2009/09/getting-more-flow-from-your-window.html"&gt;read more ranting about poorly chosen keyboard shortcuts&lt;/a&gt;.)&lt;/li&gt;
      &lt;li&gt;I don't use the numpad often enough to justify having one.&lt;/li&gt;
      &lt;li&gt;I like having the free desk space. And not having to reach as far for the mouse when I want to use it.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;I like how thin the keyboard is (it's sort of wedge-shaped, and only about half an inch thick at the home row). At first I didn't think this would matter, but I definitely end up contorting my wrists much less than with my old keyboard.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And, to boot, it looks very classy&amp;mdash; the picture above doesn't really do it justice.&lt;/p&gt;
&lt;p&gt;Thinkpad keyboards do have some quirks (e.g. Fn key placement). I don't mind these anymore, but I know some people do. So perhaps the most useful thing that I can say in this review is that there are no surprises, as far as I can tell. If you've used a Thinkpad, you probably already know whether you want one of these Thinkpad keyboards.&lt;/p&gt;
&lt;p&gt;The only reservation I have is that the keys seem to be spaced a little further apart than I'm used to (having become acclimated to the X series keyboards). I'm presuming that this is something I'll get used to over time, so I'm not worrying yet.&lt;/p&gt;
&lt;p&gt;Kudos to David Hill and his team for a job well done.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://shop.lenovo.com/SEUILibrary/controller/e/web/LenovoPortal/en_US/catalog.workflow:item.detail?GroupID=38&amp;Code=55Y9003&amp;current-category-id=E9ADAEB6787146E29B78400A33E7FE8A"&gt;ThinkPad Keyboard at the Lenovo Store&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Additional notes on GNU/Linux support:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;All the special keys (that I tried, anyway&amp;mdash; volume, mute, and media player control) work out of the box on Ubuntu GNU/Linux 9.04.&lt;/li&gt;
  &lt;li&gt;TrackPoint scrolling works, too. Follow &lt;a href="http://psung.blogspot.com/2008/09/scrolling-with-thinkpads-trackpoint-in.html"&gt;the instructions here&lt;/a&gt;, except in &lt;tt&gt;mouse-wheel.fdi&lt;/tt&gt;, use &lt;tt&gt;"Lite-On Technology Corp. ThinkPad USB Keyboard with TrackPoint"&lt;/tt&gt; instead of &lt;tt&gt;"TPPS/2 IBM TrackPoint"&lt;/tt&gt;. (In general, it looks like you can figure out the right &lt;tt&gt;info.product&lt;/tt&gt; string to use by running &lt;tt&gt;xinput list&lt;/tt&gt; and finding the right device from the list.)&lt;/li&gt;
&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-872017476010699553?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/872017476010699553/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/09/new-external-thinkpad-keyboard.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/872017476010699553'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/872017476010699553'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/09/new-external-thinkpad-keyboard.html' title='New external Thinkpad keyboard'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_egN-3IJO0Xg/SrBm8z268jI/AAAAAAAACew/Hbbt0hzC-Xw/s72-c/Think-KB-toe1.JPG' height='72' width='72'/><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7131820954389994406</id><published>2009-09-09T00:21:00.000-07:00</published><updated>2010-09-29T22:06:52.515-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Getting more "flow" from your window manager</title><content type='html'>&lt;p&gt;Working on a Thinkpad keyboard is &lt;a href="http://philipsung.blogspot.com/2008/03/thinkpad-x61s-and-lenovo-scrollpoint.html"&gt;pure&lt;/a&gt; &lt;a href="http://psung.blogspot.com/2008/09/scrolling-with-thinkpads-trackpoint-in.html"&gt;bliss&lt;/a&gt;. The Trackpoint lets me point (and scroll!) without moving my wrists; within Emacs/&lt;a href="http://psung.blogspot.com/2008/10/stupid-screen-tricks.html"&gt;screen&lt;/a&gt;, even it is superfluous. Being able to &lt;em&gt;immediately&lt;/em&gt; act on one's intentions is an important factor in attaining a state of &lt;a href="http://en.wikipedia.org/wiki/Flow_(psychology)"&gt;&lt;b&gt;flow&lt;/b&gt;&lt;/a&gt;, and there is a huge psychological difference between being able to do something "now" and "wait, hang on for 500ms so I can reach the touchpad." When I'm really in the zone, I can actually notice my concentration dissipating if I need to reach for the arrow keys, or worse, the mouse or touchpad (this is hard to explain to people who don't use Emacs or Vim!).&lt;/p&gt;
&lt;p&gt;&lt;b&gt;But window managers are still awful&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Yet, even if I'm using Emacs and/or a web browser 90% of the time, and even supposing they left nothing to be desired, there's another program I have to interact with near 100% of the time: the window manager.&lt;/p&gt;
&lt;p&gt;It's a shame, but few of the usability lessons we learned over the years made it to any of the common window managers&amp;mdash; Windows, Mac, or Metacity. The window manager acts an intermediary sitting between the user and &lt;em&gt;every single app&lt;/em&gt;, but WM functions are often marginalized and too hard to activate. This is especially unfortunate, because now that huge monitors are commonplace, we actually need better WMs to help us effectively use that screen space&amp;mdash; maximize and minimize alone don't cut it anymore! (Jeff Atwood &lt;a href="http://www.codinghorror.com/blog/archives/000928.html"&gt;pointed this out&lt;/a&gt; all the way back in 2007.)&lt;/p&gt;
&lt;p&gt;How can we do better? Well, what does "better" even mean? Here are the assumptions I'm operating under, about what kinds of operations are easy or hard to perform:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;"Reaching is hard": reaching touch-typeable keys is easier than reaching the function keys (F1 &amp;hellip; F12), the arrow keys, or the numpad.&lt;/li&gt;
  &lt;li&gt;"Pointing is hard": typing a small number of keystrokes is easier than using the mouse (or any other pointing device).&lt;/li&gt;
  &lt;li&gt;"&lt;a href="http://en.wikipedia.org/wiki/Fitts's_law"&gt;Fitts's law&lt;/a&gt;": pointing at a large target with the mouse (e.g. a window) is easier than pointing at a small target (e.g. an icon, menu, button, border, or title bar).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You may be able to see where the problems are. Windows and Metacity map a bunch of window management functions to far-away placed keys like &lt;tt&gt;Alt+F4&lt;/tt&gt; and &lt;tt&gt;Alt+F10&lt;/tt&gt;. Mac OS has better bindings for some functions, but doesn't map Maximize at all by default, instead providing access via itty-bitty buttons on each window. On both Windows and Mac OS, the fastest way to move (or resize) a window is by dragging it by its title bar (or resize handle). It doesn't get any worse than that.&lt;/p&gt;
&lt;p&gt;Dragging resize handles&amp;hellip; seriously? Fitts's law, anyone? This is nonsense.&lt;/p&gt;
&lt;p&gt;This is the main reason that I can only use Windows or Mac OS for about 30 seconds before my blood pressure starts to go up. They are &lt;em&gt;not usable&lt;/em&gt;. Having to fish around with the pointer every time you want to do something is also a great way to develop RSI.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Building a better WM&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I've played around with a few scattered ideas with the goal of making a better WM for myself. I've implemented these in my &lt;a href="http://icculus.org/openbox/index.php/Main_Page"&gt;Openbox&lt;/a&gt; config, although any reasonably configurable WM will do.&lt;/p&gt;
&lt;p&gt;But, I would like to stress here, &lt;a href="http://www.basicinstructions.net/?p=1161"&gt;the details are unimportant&lt;/a&gt;. If you can find the parts of your workflow that are unnecessarily slow, and eliminate them, more power to you.&lt;/p&gt;
&lt;p&gt;1. Manage windows and workspaces with shortcuts that &lt;b&gt;don't require function keys or arrow keys&lt;/b&gt;. For example, &lt;tt&gt;Alt+F10&lt;/tt&gt; (maximize a window) and &lt;tt&gt;Ctrl+Alt+LeftArrow&lt;/tt&gt; (switch workspaces) are out. In my setup they are replaced by &lt;tt&gt;Win+1&lt;/tt&gt; and &lt;tt&gt;Win+j&lt;/tt&gt;, respectively.&lt;/p&gt;
&lt;p&gt;2. Move and resize windows with &lt;b&gt;alt-dragging&lt;/b&gt; (actually, Win-key dragging). When you want to move or resize the window, &lt;em&gt;the entire window is your drag target&lt;/em&gt;. No need to aim for the title bar, or the resize handle, or the window border. Fitts's law, suckers.&lt;/p&gt;
&lt;p&gt;To move windows: point at the window, hold down &lt;tt&gt;Win&lt;/tt&gt;, and drag with the left mouse button. To resize windows: point at the window anywhere near the corner you want to move, hold down &lt;tt&gt;Win&lt;/tt&gt;, and drag with the right mouse button.&lt;/p&gt;
&lt;p&gt;Kudos to Metacity (and most other X WMs) for shipping with something similar by default.&lt;/p&gt;
&lt;p&gt;3. &lt;b&gt;Arrange windows using the keyboard&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;It took me the longest time to realize that this was something that would actually be useful.&lt;/p&gt;
&lt;p&gt;Most people only have a couple of common ways they like to arrange windows on the screen&amp;mdash; for example, one window filling the entire screen, or two half-width windows side by side. What this means is that in the common case, you are really not asking for windows to be placed at specific pixel positions on your screen. Hence, the mouse isn't actually needed.&lt;/p&gt;
&lt;p&gt;I use a couple of different window management "idioms," which are probably best illustrated by example:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;tt&gt;Win+s i j k RET&lt;/tt&gt;, for example expands the current window until it meets the nearest edge to the north, west, and south. Before and after:&lt;/p&gt;
    &lt;p&gt;&lt;img src="http://lh4.ggpht.com/_egN-3IJO0Xg/SqXkKAnKlOI/AAAAAAAABno/nDKcd4jIuAM/s1.jpg"&gt;
      &lt;img src="http://lh5.ggpht.com/_egN-3IJO0Xg/SqXkKGX763I/AAAAAAAABns/rgBACED5C5w/s2.jpg"&gt;&lt;/p&gt;
    &lt;p&gt;&lt;tt&gt;Win+s&lt;/tt&gt; activates window-expanding and &lt;tt&gt;i&lt;/tt&gt;, &lt;tt&gt;j&lt;/tt&gt;, &lt;tt&gt;k&lt;/tt&gt;, and &lt;tt&gt;l&lt;/tt&gt; indicate north, west, south, and east, respectively.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;tt&gt;Win+s Win+s&lt;/tt&gt; means "expand the current window as much as possible without covering anything else," which seems like a common thing to want. Before and after:&lt;/p&gt;
    &lt;p&gt;&lt;img src="http://lh6.ggpht.com/_egN-3IJO0Xg/SqXkKRTnBSI/AAAAAAAABnw/q0JBnrIt6dA/s3.jpg"&gt;
      &lt;img src="http://lh4.ggpht.com/_egN-3IJO0Xg/SqXkKQ9xO6I/AAAAAAAABn0/dJOS1gudFek/s4.jpg"&gt;&lt;/p&gt;
    &lt;p&gt;Openbox's &lt;tt&gt;smart&lt;/tt&gt; &lt;a href="http://icculus.org/openbox/index.php/Configuration#Placement"&gt;window placement policy&lt;/a&gt; attempts to place a second window within the space left by the first one. So a quick &lt;tt&gt;Win+s Win+s&lt;/tt&gt; makes a second window neatly fill up all the space left unused by the first one!&lt;/p&gt;
    &lt;p&gt;For more complex arrangements, it's very fast to drag a window to an &lt;em&gt;approximate&lt;/em&gt; location (see alt-dragging, above), then use &lt;tt&gt;Win+s Win+s&lt;/tt&gt; to make it neatly fill the available space.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;tt&gt;Win+w&lt;/tt&gt; is analagous to &lt;tt&gt;Win+s&lt;/tt&gt; except that it moves a window to the nearest edge to the north/west/south/east instead of resizing it.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;An alternative strategy is to bind keys to move windows to a small number of fixed "slots," such as the two halves of a screen. Jeff Atwood &lt;a href="http://web.psung.name/openbox/"&gt;mentions this strategy&lt;/a&gt; and its implementation in WinSplit Revolution.&lt;/p&gt;
&lt;p&gt;4. Configure single-key &lt;b&gt;shortcuts for launching common apps&lt;/b&gt;. For example, &lt;tt&gt;Win+b&lt;/tt&gt; for a web browser. Not always a window-manager responsibility, but it can really streamline one's work.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Although I am still experimenting with some aspects of this setup, I am fairly happy with it. For better or for worse it does feel a lot like a "normal" window manager, just one that is highly streamlined (and doesn't give me hypertension). I'd be curious to see what additional improvements can be gained by giving up some of the associated flexibility and moving to a more restrictive model (e.g. something like a tiling WM).&lt;/p&gt;
&lt;p&gt;For the curious, I've posted Openbox configuration recipes for tips 2 and 3 &lt;a href="http://web.psung.name/openbox/"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7131820954389994406?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7131820954389994406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/09/getting-more-flow-from-your-window.html#comment-form' title='11 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7131820954389994406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7131820954389994406'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/09/getting-more-flow-from-your-window.html' title='Getting more &quot;flow&quot; from your window manager'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_egN-3IJO0Xg/SqXkKAnKlOI/AAAAAAAABno/nDKcd4jIuAM/s72-c/s1.jpg' height='72' width='72'/><thr:total>11</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5935097473388425842</id><published>2009-08-24T21:58:00.000-07:00</published><updated>2011-09-07T19:41:15.365-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><category scheme='http://www.blogger.com/atom/ns#' term='LaTeX'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>AUCTeX and preview-latex</title><content type='html'>&lt;p&gt;&lt;a href="http://www.gnu.org/software/auctex/"&gt;AUCTeX&lt;/a&gt; is a TeX mode for Emacs that adds various conveniences for editing LaTeX (and other macro packages). One of its killer features is inline previews of math and graphics, using &lt;a href="http://www.gnu.org/software/auctex/preview-latex.html"&gt;preview-latex&lt;/a&gt;:&lt;/p&gt;
&lt;p style="text-align: center"&gt;&lt;a href="http://lh6.ggpht.com/_egN-3IJO0Xg/SpIj6AtHOTI/AAAAAAAABj8/O1aKgTb-Njw/preview-latex.png"&gt;&lt;img style="margin: 0; border: 1px black solid;" src="http://lh6.ggpht.com/_egN-3IJO0Xg/SpImc2gIlrI/AAAAAAAABkI/pY2MNrFeAVY/preview-latex-small.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;With AUCTeX and preview-latex, you can properly edit your document and equations in their high-level (TeX source) representation, while getting near-instant confirmation that your equations will turn out the way you want. It's pretty much the best of both worlds.&lt;/p&gt;
&lt;p&gt;AUCTeX is easy to set up on Ubuntu, although it takes slightly more work than the usual &lt;tt&gt;apt-get&lt;/tt&gt; invocation. Here is a HOWTO for my future reference (and yours). This has been tested on Ubuntu 9.04 with a post-v23-release &lt;a href="https://launchpad.net/~ubuntu-elisp/+archive/ppa"&gt;emacs-snapshot&lt;/a&gt;:&lt;/p&gt;
&lt;p&gt;Install AUCTeX.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;pre&gt;$ sudo aptitude install auctex&lt;/pre&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Add the following init code to your &lt;tt&gt;.emacs&lt;/tt&gt; file.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;pre&gt;(load "auctex.el" nil t t)
(load "preview-latex.el" nil t t)&lt;/pre&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Open a LaTeX file in Emacs and press &lt;tt&gt;C-c C-p C-b&lt;/tt&gt; (&lt;tt&gt;M-x preview-buffer&lt;/tt&gt;) to generate math/graphics previews for the entire buffer. After you update an equation, press &lt;tt&gt;C-c C-p C-p&lt;/tt&gt; (&lt;tt&gt;M-x preview-at-point&lt;/tt&gt;) to refresh the preview.&lt;/p&gt;
&lt;p&gt;Further reading: &lt;a href="http://www.gnu.org/software/auctex/"&gt;AUCTeX&lt;/a&gt;, &lt;a href="http://www.gnu.org/software/auctex/manual/auctex.index.html"&gt;AUCTeX manual&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5935097473388425842?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5935097473388425842/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/08/auctex-and-preview-latex.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5935097473388425842'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5935097473388425842'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/08/auctex-and-preview-latex.html' title='AUCTeX and preview-latex'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_egN-3IJO0Xg/SpImc2gIlrI/AAAAAAAABkI/pY2MNrFeAVY/s72-c/preview-latex-small.png' height='72' width='72'/><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-1226458450382059712</id><published>2009-08-17T19:18:00.000-07:00</published><updated>2009-08-21T13:04:20.207-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zeya'/><title type='text'>Zeya 0.1</title><content type='html'>&lt;p&gt;&lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt; is a streaming music server that supports an HTML 5 &lt;span style="font-size: smaller"&gt;(draft standard)&lt;/span&gt; based player.&lt;/p&gt;
&lt;p align="center"&gt;&lt;a href="http://web.psung.name/zeya/zeya.png"&gt;&lt;img src="http://web.psung.name/zeya/zeya-cropped.png" style="border: 0"&gt;&lt;/a&gt;&lt;br&gt;&lt;em&gt;Motto: bring your music anywhere&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I'm pleased to announce the first numbered release of Zeya, version 0.1.&lt;/p&gt;
&lt;p&gt;Notable new features:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Support for the &lt;strong&gt;directory backend&lt;/strong&gt;, which scans a directory recursively and serves up all the music in it. Invoke with&lt;br&gt;&lt;tt&gt;&amp;nbsp;&amp;nbsp;zeya.py --backend=dir --path=/path/to/music&lt;/tt&gt;&lt;/li&gt;
&lt;li&gt;Experimental support for &lt;strong&gt;Google Chrome&lt;/strong&gt; clients. Zeya plays music in Chrome. Latency is still poor and advance-to-next-track is broken for the time being. Read the README for the gory details.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Keyboard shortcuts&lt;/strong&gt; for play controls: &lt;tt&gt;j&lt;/tt&gt;, &lt;tt&gt;k&lt;/tt&gt;, and &lt;tt&gt;SPC&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Visit &lt;tt&gt;&lt;a href="http://web.psung.name/zeya/"&gt;http://web.psung.name/zeya/&lt;/a&gt;&lt;/tt&gt; for more information, and read the &lt;a href="http://psung.blogspot.com/2009/07/zeya-bring-your-music-anywhere.html"&gt;previous blog post on Zeya&lt;/a&gt; for a bit more context.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-1226458450382059712?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/1226458450382059712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/08/zeya-01.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1226458450382059712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1226458450382059712'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/08/zeya-01.html' title='Zeya 0.1'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2075084529958867914</id><published>2009-08-10T18:20:00.000-07:00</published><updated>2009-08-10T18:24:12.093-07:00</updated><title type='text'>Google Web Toolkit and Java/JS translation</title><content type='html'>&lt;p&gt;I've been using &lt;a href="http://code.google.com/webtoolkit/"&gt;Google Web Toolkit&lt;/a&gt; for some projects at work, and I've been quite impressed with it. I think that for many classes of web apps, GWT (or something with the same general model) is really the "right" way to build your app.&lt;/p&gt;
&lt;p&gt;(Disclosure: these were the first nontrivial web apps I've written since before the term "AJAX" came into common parlance, so I've not been totally in the loop for some time with respect to web programming or any of the major JS libraries.)&lt;/p&gt;
&lt;p&gt;For the uninitiated: GWT is a free software development stack that lets web developers write apps entirely in Java. GWT provides various UI and utility libraries, as well as a compiler that compiles your Java code to a combination of Java servlets and client-side Javascript&amp;mdash; including the XMLHttpRequest serialization/deserialization code needed at the client/server boundary.&lt;/p&gt;
&lt;p&gt;I don't have anything against Javascript or dynamic languages. But I think that for certain web apps it can make sense to trade away some of the flexibility of Javascript. In many web apps today, the app is just the frontend to some database, and the client's responsibility is mainly just to manipulate the DOM and shuttle data around. Not a whole lot of business logic&amp;mdash; although, to be fair, JS apps will likely become more and more sophisticated in the future. I suspect many of these apps might be better served by a strongly typed language. The GWT Java compiler prevents entire classes of errors right off the bat, including the most common type in JS apps in my experience: typos. (Yeah, unit tests and tools will also mitigate these problems a bit.)&lt;/p&gt;
&lt;p&gt;However, I think the most important idea at the core of GWT is that of a language-to-language translator. &lt;b&gt;The problem with pure Javascript is that the code you want to be writing and maintaining does not look at all like the code you want the browser to be executing.&lt;/b&gt; The idea of an intermediate translation step is not new: people have been using Javascript minifiers/obfuscators for years to speed up loading and execution. But GWT takes this further: in addition to shortening identifiers, it aggressively inlines code and eliminates dead code (unused variables, fields, methods, classes, ...). Now you're free to introduce indirection in your code to make it more readable and testable (for example, refactoring to the &lt;a href="http://en.wikipedia.org/wiki/Model-view-presenter"&gt;model-view-presenter&lt;/a&gt; pattern) without feeling guilty that you are making your app slower. (Testability! Hooray!) This eliminates some of the usual tension between speed and maintainability.&lt;/p&gt;
&lt;p&gt;Actually, GWT takes its translation process even further: it compiles multiple browser-specific versions of your app&amp;mdash; something that few, if any, humans would bother to do&amp;mdash; so that no client ever has to load or execute switch-on-browser logic and each client gets a variant optimized for its platform.&lt;/p&gt;
&lt;p&gt;When all these optimizations are considered, Google claims that GWT-generated code is "&lt;a href="http://code.google.com/webtoolkit/overview.html"&gt;often ... faster than equivalent handwritten Javascript&lt;/a&gt;." That shouldn't be surprising: code that is to be maintained has to meet some minimum standard of readability, but code that is to be executed has no such requirement. This really drives home the importance, and the power, of having a source-to-source translation process in the pipeline.&lt;/p&gt;
&lt;p&gt;(There are a number of other compelling reasons to use GWT that I haven't mentioned here. The GWT page gives a pretty good &lt;a href="http://code.google.com/webtoolkit/overview.html"&gt;overview&lt;/a&gt; of them.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2075084529958867914?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2075084529958867914/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/08/google-web-toolkit-and-javajs.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2075084529958867914'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2075084529958867914'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/08/google-web-toolkit-and-javajs.html' title='Google Web Toolkit and Java/JS translation'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5783636807049725751</id><published>2009-07-29T20:49:00.000-07:00</published><updated>2009-07-30T09:42:06.126-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Emacs 23</title><content type='html'>&lt;p&gt;Emacs 23 has been released. You can &lt;a href="http://ftp.gnu.org/gnu/emacs/"&gt;download it from GNU's FTP server&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The most notable new features or changes that I noticed or have been using:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A single Emacs process can generate frames on any number of TTYs and on X simultaneously. Run &lt;tt&gt;M-x server-start&lt;/tt&gt; and then &lt;tt&gt;emacsclient -t&lt;/tt&gt; or &lt;tt&gt;emacsclient -c&lt;/tt&gt; to create a new TTY or X frame, respectively.&lt;/li&gt;
&lt;li&gt;&lt;tt&gt;C-p&lt;/tt&gt; and &lt;tt&gt;C-n&lt;/tt&gt; now move by screen/visual lines instead of by logical lines. While this makes Emacs more consistent with most modern apps, it has the potential to break keyboard macros. If you use macros frequently, consider setting &lt;tt&gt;(setq line-move-visual nil)&lt;/tt&gt; to disable this behavior.&lt;/li&gt;
&lt;li&gt;Transient Mark mode is enabled by default. I find &lt;tt&gt;t-m-m&lt;/tt&gt; is occasionally really handy, especially after the &lt;tt&gt;mark-*&lt;/tt&gt; commands, and for restricting the region for &lt;tt&gt;query-replace&lt;/tt&gt;. However, I think &lt;tt&gt;t-m-m&lt;/tt&gt; highlights a little too aggressively. To disable &lt;tt&gt;t-m-m&lt;/tt&gt; except after the &lt;tt&gt;mark-*&lt;/tt&gt; commands, I use the following:&lt;/li&gt;
&lt;blockquote&gt;&lt;pre&gt;(transient-mark-mode 0)

;; Activate t-m-m only after mark-* commands (you can also enable it manually
;; at any time with C-u C-x C-x).
(require 'cl)
(macrolet
    ((advise (&amp;rest commands)
             `(progn
                ,@(mapcar (lambda (command)
                            `(defadvice ,command (after transient-mark activate)
                               "Activate Transient Mark mode temporarily."
                               (setq transient-mark-mode '(only))))
                          commands))))
  (advise mark-sexp
          mark-word
          mark-paragraph
          mark-defun
          mark-end-of-sentence
          mark-page
          mark-whole-buffer
          LaTeX-mark-environment
          LaTeX-mark-section))&lt;/pre&gt;&lt;/blockquote&gt;
&lt;li&gt;&lt;tt&gt;C-l&lt;/tt&gt; is bound to &lt;tt&gt;recenter-top-bottom&lt;/tt&gt;, which moves the viewable area so that the current line is at the center, top, or bottom on successive presses. Useful for surveying the area around point.&lt;/tt&gt;
&lt;li&gt;DocView mode, new, is a PDF/PostScript/DVI viewer.&lt;/li&gt;
&lt;li&gt;Emacs is smarter about splitting windows (e.g. after &lt;tt&gt;C-x 4 C-f&lt;/tt&gt;), splitting vertically if your frame is sufficiently wide.&lt;/li&gt;
&lt;li&gt;Beautiful anti-aliased fonts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are many, many, more changes. See &lt;tt&gt;&lt;a href="http://cvs.savannah.gnu.org/viewvc/emacs/etc/NEWS?root=emacs&amp;view=markup"&gt;etc/NEWS&lt;/a&gt;&lt;/tt&gt; for the gory details.&lt;/p&gt;
&lt;p&gt;On &lt;tt&gt;emacs-devel&lt;/tt&gt;, I recently got a pointer to &lt;a href="http://www.gnu.org/software/emacs/emacs-paper.html"&gt;Richard Stallman's 1981 paper on the design of Emacs&lt;/a&gt;, presented at the ACM Conference on Text Processing:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Extensibility means that the user can add new editing commands or change old ones to fit his editing needs, while he is editing. EMACS is written in a modular fashion, composed of many separate and independent functions. The user extends EMACS by adding or replacing functions, writing their definitions in the same language that was used to write the original EMACS system. We will explain below why &lt;b&gt;this is the only method of extension which is practical in use: others are theoretically equally good but discourage use, or discourage nontrivial use&lt;/b&gt;.&lt;/p&gt;&lt;p&gt;
Extensibility makes EMACS more flexible than any other editor. Users are not limited by the decisions made by the EMACS implementors. What we decide is not worth while to add, the user can provide for himself. He can just as easily provide his own alternative to a feature if he does not like the way it works in the standard system.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;It is striking how so little software today, even "professional" software that users are apt to use 8 hours a day, is actually designed to facilitate extensibility and automation by users.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5783636807049725751?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5783636807049725751/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/07/emacs-23.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5783636807049725751'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5783636807049725751'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/07/emacs-23.html' title='Emacs 23'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7455109190630249849</id><published>2009-07-24T22:20:00.000-07:00</published><updated>2009-07-24T22:44:31.888-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Zeya'/><title type='text'>Zeya: bring your music anywhere</title><content type='html'>&lt;p&gt;I love SSH. One reason is that I love being able to get to my files from anywhere on the planet without any advance planning.&lt;/p&gt;
&lt;p&gt;After using SSH for a while, carrying my bits around with me on magnetized platters or EEPROMs inside a laptop/phone/PMP just seems so quaint and irritating. It leads to a host of problems: you have to worry about synchronizing, deciding what to synchronize, merging changes, and misplacing your device. Usually, some bizarre cable is involved in transferring data. And invariably, there's that one spreadsheet, paper, song, or ebook that you tragically can't view because &lt;em&gt;you left it on your computer at home&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;(Incidentally, I think using cloud hosted storage/apps is one approach, but not a complete solution, at least yet.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Introducing Zeya&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;While SSH is great for the vast majority of application classes, I think effectively accessing audio/video remotely requires more specialized tools.&lt;/p&gt;
&lt;p&gt;To this end, I spent a few days writing &lt;a href="http://web.psung.name/zeya/"&gt;Zeya&lt;/a&gt;, a music server that takes your Rhythmbox music collection and streams songs from it to you. However, unlike &lt;a href="http://www.gnu.org/software/gnump3d/"&gt;gnump3d&lt;/a&gt; or &lt;a href="http://ampache.org/"&gt;ampache&lt;/a&gt;, Zeya presents a full music player right in your web browser, using the goodness of HTML 5. &lt;b&gt;No Flash&lt;/b&gt;, no Silverlight, no Java applets, no plugins, no popups, no invoking external players, no client-side software installation.&lt;/p&gt;
&lt;p style="text-align: center"&gt;&lt;a href="http://web.psung.name/zeya/zeya.png"&gt;&lt;img src="http://web.psung.name/zeya/zeya-cropped.png" style="border: 0"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Zeya brings your music to any computer with a web browser (OK, as long as the browser is Firefox 3.5, for the moment). Play songs from your collection on your desktop at work. Or on your netbook at Starbucks. And now or soon, when you get a current-gen web browser on your phone/MID/fridge, you can bring all your music there too.&lt;/p&gt;
&lt;p&gt;Picture iTunes' library sharing. Now imagine that its functionality wasn't &lt;a href="http://en.wikipedia.org/wiki/Digital_Audio_Access_Protocol#DAAP_authentication"&gt;crippled&lt;/a&gt; to lock users in to iTunes. Oh, and you could actually access it from outside your LAN. Oh, and that you could listen from any computer, anywhere, without installing any software. I think Zeya in its current state is just a pale shadow of what is really possible when you actually try to make information &lt;em&gt;really easy&lt;/em&gt;, rather than just &lt;em&gt;marginally less difficult&lt;/em&gt;, to get to.&lt;/p&gt;
&lt;p&gt;Samson Yeung and I have been working on, and using, Zeya for a few days now. It's pretty useful and easy to get running, but it is feature-bare, experimental, and subject to change in all sorts of fun and interesting ways. If that doesn't scare you, visit&lt;/p&gt;
&lt;p style="text-align: center"&gt;&lt;tt&gt;&lt;a href="http://web.psung.name/zeya/"&gt; http://web.psung.name/zeya/&lt;/a&gt;&lt;/tt&gt;,&lt;/p&gt;
&lt;p&gt;try it out, and let me know what you think.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7455109190630249849?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7455109190630249849/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/07/zeya-bring-your-music-anywhere.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7455109190630249849'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7455109190630249849'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/07/zeya-bring-your-music-anywhere.html' title='Zeya: bring your music anywhere'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4640063964112562183</id><published>2009-07-01T22:11:00.000-07:00</published><updated>2009-07-09T20:58:40.338-07:00</updated><title type='text'>Why I can't afford proprietary software</title><content type='html'>&lt;p&gt;The following happened at the lab a few months ago:&lt;/p&gt;
&lt;pre&gt;Date: Fri, 12 Dec 2008 12:16:52 -0500
To: matlab-users

Hi All,

Seems we've exceeded our pool of Matlab licenses.  We will be getting
more but unfortunately it takes 5-10 days to do so.

In the mean time please don't take up any more licenses than you
absolutely need and close instances you are not using.  We have some
people with tight paper deadlines that are unable to get licenses.

Thanks for your cooperation in this.&lt;/pre&gt;
&lt;p&gt;Just like that, for a handful of people, research work slowed to a crawl for almost a week at the end of the semester.&lt;/p&gt;
&lt;p&gt;This kind of stuff makes my blood boil. There is no logical reason we have to &lt;em&gt;ration&lt;/em&gt; software as if it were gasoline. But that's another rant. Enforcing unfortunate license restrictions is &lt;em&gt;completely&lt;/em&gt; within The Mathworks' rights under the law.&lt;/p&gt;
&lt;p&gt;I bring this up because I think it hints at the elephant in the room, namely:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;When you use proprietary software on your computer, it's not your computer anymore.&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;That's the reason I'll talk my head off about &lt;a href="http://www.fsf.org/about/what-is-free-software"&gt;free software&lt;/a&gt; and the reason I'm not going to stand for Matlab, Windows, Mac OS, Microsoft Office, the iPhone, , the Kindle, Flash, Skype, etc.&amp;mdash; none of it. (Mathematica is a jaw-dropping technical achievement. And I still won't touch it with a ten-foot pole.) The moral of the story is not that you should double-check your Matlab license paperwork. No, this is par for the course, and just a symptom of the real problem: that proprietary software companies &lt;a href="http://apple.slashdot.org/article.pl?sid=08/09/21/122225"&gt;can&lt;/a&gt; &lt;a href="https://bugs.launchpad.net/banshee/+bug/62842"&gt;enforce&lt;/a&gt; &lt;a href="http://gizmodo.com/303171/apple-says-unlocked-iphones-will-brick-after-software-update-+-what-does-it-mean"&gt;totally&lt;/a&gt; &lt;a href="http://news.cnet.com/8301-13579_3-10273717-37.html"&gt;capricious&lt;/a&gt; &lt;a href="http://www.usatoday.com/tech/news/computersecurity/2006-02-16-apple-hackers_x.htm"&gt;and&lt;/a&gt; &lt;a href="http://toucharcade.com/2009/06/20/full-commodore-64-emulator-rejected-from-app-store/"&gt;arbitrary&lt;/a&gt; &lt;a href="http://blogs.zdnet.com/microsoft/?p=522"&gt;restrictions&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/Skype_Protocol"&gt;on&lt;/a&gt; &lt;a href="http://www.schneier.com/blog/archives/2007/02/drm_in_windows_1.html"&gt;what&lt;/a&gt; &lt;a href="http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.html"&gt;we&lt;/a&gt; &lt;a href="http://blogs.zdnet.com/Bott/?p=220"&gt;can&lt;/a&gt; &lt;a href="http://www.geardiary.com/2009/06/21/kindlegate-confusion-abounds-regarding-kindle-download-policy/"&gt;and&lt;/a&gt; &lt;a href="http://www.engadget.com/2009/04/16/amazon-suspends-kindle-account-after-too-many-product-returns/"&gt;can't&lt;/a&gt; &lt;a href="http://www.engadget.com/2009/06/12/blu-ray-gets-managed-copy-next-year-requries-new-hardware/"&gt;do&lt;/a&gt; &lt;a href="http://www.macworld.com/article/137148/2008/11/hdcp.html"&gt;with&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/ITunes_Store#Digital_rights_management"&gt;our&lt;/a&gt; &lt;a href="http://arstechnica.com/microsoft/news/2008/04/drm-sucks-redux-microsoft-to-nuke-msn-music-drm-keys.ars"&gt;computers&lt;/a&gt;, and that they have a well-documented history of doing so. So the less we have to rely on them, the better.&lt;/p&gt;
&lt;p&gt;I am always a bit incredulous when people advocate proprietary software on the basis of things like ease of use or good design or shininess or intuitiveness or speed or usability or "it just works" or architectural superiority or elegance. It's not that I don't value those things. I'm an engineer myself, so I appreciate the effort that goes into making things work and work well. But what good is speed if you can't go anywhere? What good is usability if you can't fucking &lt;em&gt;use&lt;/em&gt; your software? If you don't have two shreds of basic personal autonomy, worrying about other things seems kind of superfluous, no?&lt;/p&gt;
&lt;p&gt;(It's just galling how most proprietary software has awful usability, but that's also another rant.)&lt;/p&gt;
&lt;p&gt;You are probably skeptical, and rightfully so, about the true magnitude of the problem I'm complaining about here. This is not just an issue with a few bad apples (as it were...). It's a fundamental problem of incentives. When you pay for a license for bits, the vendor has an incentive to protect future sales by curtailing the possible uses of those bits. They certainly have the power to enforce whatever restrictions they wish and to change them up at any time. And they'll put time and effort into it, because you can't remove, inspect, or enumerate those restrictions. Maybe you think things are not so bad now, and indeed, maybe they aren't. But the rules can change arbitrarily and at any time, and I mean &lt;em&gt;arbitrarily and at any time&lt;/em&gt;. (Three words: iPhone app store.) In the world of proprietary software, there are no sure things.&lt;/p&gt;
&lt;p&gt;To put it succinctly, if you don't have the &lt;a href="http://www.gnu.org/philosophy/free-sw.html"&gt;four freedoms&lt;/a&gt;, the people who make your software have the means, the motive, and the opportunity to cripple their products to extract as much money from you as they can. There is something deeply perverse and broken about this kind of business model. Remember the lesson from game theory: trust people when, and only when, it's in their best interest to help you.&lt;/p&gt;
&lt;p&gt;It's not that I can't afford to pay for nice things. (What's $29, or even $1399, if it helps you get your job done? A bargain!) What I can't afford is paying for the privilege of letting someone have me by the throat (or elsewhere).&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4640063964112562183?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4640063964112562183/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/07/why-i-cant-afford-proprietary-software.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4640063964112562183'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4640063964112562183'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/07/why-i-cant-afford-proprietary-software.html' title='Why I can&apos;t afford proprietary software'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6724041043570642640</id><published>2009-06-18T21:57:00.000-07:00</published><updated>2011-09-07T19:44:57.757-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LaTeX'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Making your own page-a-day calendar</title><content type='html'>&lt;p&gt;Anomalously, today's post is about a DIY physical artifact.&lt;/p&gt;
&lt;p&gt;A while back, I made a custom page-a-day calendar as a gift for my girlfriend. Each page tears off and has a picture on it. (Unfortunately, I don't have any photos of the finished product.)&lt;/p&gt;
&lt;p&gt;With just a little effort, you can make one of these things and have it look quite professional. You can fill the pages with whatever photos, comics, etc. you want. And, I can virtually guarantee you, your recipient has never had a page-a-day calendar typeset in Computer Modern.&lt;/p&gt;
&lt;p align="center"&gt;
  &lt;img src="http://lh6.ggpht.com/_egN-3IJO0Xg/Sjw9BP0hN0I/AAAAAAAABW8/04mBWBEpTzE/page.png" width="482" height="322"&gt;
&lt;/p&gt;

&lt;p&gt;Here are skeletal instructions for making your own. You'll need a printer, ink or toner, most of a ream of paper, some &lt;em&gt;padding compound&lt;/em&gt;, a paper cutting device/facility, cardboard, LaTeX, and time.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;1. Get source images&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Acquire 365 images from Flickr, your photo collection, your favorite CC-licensed webcomic, or whatever strikes your fancy. &lt;a href="http://psung.blogspot.com/2008/06/using-wget-or-curl-to-download-web.html"&gt;This post on &lt;tt&gt;curl&lt;/tt&gt;&lt;/a&gt; may come in handy. Some notes: (1) Layout is much easier if the images are the same aspect ratio. (2) Consider upsampling the images if needed, e.g. with imagemagick, so you can print at a respectable DPI. Henceforth I'll assume you've named the images &lt;tt&gt;imgs/001.jpg&lt;/tt&gt;, &lt;tt&gt;imgs/002.jpg&lt;/tt&gt;, etc. If this is not the case, simply adjust the code in Steps 2 and 3 accordingly.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;2. Use this LaTeX skeleton&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Make a new TeX file and fill it with this:&lt;/p&gt;

&lt;pre&gt;\documentclass[17pt,oneside,final,showtrims]{memoir}
\usepackage{marvosym}

\setstocksize{11in}{8.5in}

\settrims{0in}{0in}

\settrimmedsize{4in}{6in}{*}
\settypeblocksize{3.5in}{1.75in}{*}
\setlrmargins{0.25in}{*}{*}
\setulmargins{0.05in}{*}{*}
\setheadfoot{0.01in}{0.1in}
\setheaderspaces{*}{*}{*}
\setmarginnotes{0.25in}{3.5in}{0in}

\checkandfixthelayout

\pagestyle{empty}

\usepackage[final]{graphicx}

\pagestyle{empty}

\newcommand{\daypage}[6] {
  \marginpar{\includegraphics[height=3.4in]{imgs/#1.jpg}}
  \begin{center}
    \Large{#2} \\
    \HUGE{\textbf{#3}} \\
    \large{#4}

    \vspace{0.4in}
    \small{#5}

    \vspace{0.2in}
    \scriptsize{\textit{#6}}
  \end{center}
  \newpage
}

\begin{document}
  % Cover page
  \marginpar{\includegraphics[height=3.4in]{imgs/cover.png}}
  \newpage

  \include{tex-days}
\end{document}&lt;/pre&gt;
&lt;p&gt;Salient points:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The &lt;tt&gt;\daypage&lt;/tt&gt; command generates a new page. You supply arguments specifying the parameters for each page: the filename of the image to include, the day and date, a line indicating whatever holiday it might be, etc. Play around with the layout, especially if you're using images of different aspect ratios than I did or if you have a calendar stand of a particular size.&lt;/li&gt;
  &lt;li&gt;If you want a cover page, supply a &lt;tt&gt;cover.png&lt;/tt&gt;; otherwise, remove the corresponding lines from the template.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;b&gt;3. Generate the pages&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;The template above includes &lt;tt&gt;tex-days.tex&lt;/tt&gt;, which might look something like this:&lt;/p&gt;
&lt;pre&gt;[...]
  \daypage{182}{Sunday}{03}{Jul 2005}{~}{~}
  \daypage{183}{Monday}{04}{Jul 2005}{Independence Day}{~}
  \daypage{184}{Tuesday}{05}{Jul 2005}{~}{~}
  \daypage{185}{Wednesday}{06}{Jul 2005}{~}{~}
  \daypage{186}{Thursday}{07}{Jul 2005}{~}{~}
[...]&lt;/pre&gt;
&lt;p&gt;You can generate a skeletal version of this, sans holidays, with a quick Python program. I've provided a &lt;a href="http://web.psung.name/public/tex-days.tex"&gt;sample &lt;tt&gt;tex-days.tex&lt;/tt&gt; file&lt;/a&gt; for the year 2010.&lt;/p&gt;
&lt;p&gt;The first argument on each line indicates the filename, e.g. &lt;tt&gt;182&lt;/tt&gt; indicates that &lt;tt&gt;182.jpg&lt;/tt&gt; should be included. Make sure these match the filenames you are using. The sample file assumes your images are named &lt;tt&gt;1.jpg&lt;/tt&gt;, &lt;tt&gt;2.jpg&lt;/tt&gt;, etc. If this is not the case, either create your own version or rename your files.&lt;/p&gt;
&lt;p&gt;If you're interested in embellishing the output, the 5th and 6th arguments on each line provide supplementary text to go on each page (#6 is printed in smaller type than #5). You can fill in, by hand or programmatically, whatever notations you want here, e.g., holidays, birthdays, anniversaries, or a countdown to whatever.&lt;/p&gt;
&lt;p&gt;Arguments 2, 3, and 4 give the day of week, date, and month/year respectively that are displayed, in case that wasn't clear.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;4. Produce and print&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;Run the file through &lt;tt&gt;pdflatex&lt;/tt&gt; and print it! Make sure the alignment is consistent across pages.&lt;/p&gt;

&lt;p&gt;The &lt;tt&gt;showtrims&lt;/tt&gt; argument in the template file makes LaTeX print trim marks on each page. However, you really only need trim marks on the first page. If you're obsessive-compulsive, you could print the first page with trim marks and the rest without to guarantee the marks won't show on the finished product.&lt;/p&gt;

&lt;p align="center"&gt;&lt;img src="http://lh6.ggpht.com/_egN-3IJO0Xg/Sjw9s69qpvI/AAAAAAAABXE/1p-ojmOa438/s400/layout.png" width="310" height="400"&gt;&lt;/p&gt;

&lt;p&gt;&lt;b&gt;5. Trim it&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;I took the stack of paper, with pieces of thin cardboard above and below it, to my local Kinko's (now Fedex Kinko's, I guess). I asked them to cut the stack along the trim marks (2 cuts, since 2 of the edges already run up again against the page edges). They did this for a fee of just $1/cut.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;6. Bind it&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/B0017THBRS?ie=UTF8&amp;tag=psung-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B0017THBRS"&gt;&lt;img src="http://ecx.images-amazon.com/images/I/21M1RTJMRZL._SL500_AA225_.jpg" style="float: left; border: 0; margin: 8px"&gt;&lt;/a&gt;Get some padding compound, e.g. &lt;a href="http://www.amazon.com/gp/product/B0017THBRS?ie=UTF8&amp;tag=psung-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=B0017THBRS"&gt;Sparco padding compound&lt;/a&gt;. (I bought a quart, so I can probably make gift calendars/notepads for years.) Align the cut pages, leaving one piece of cardboard on the bottom, and put the stack in a vise. (In a jam, "under a pile of hardcover books" will do.) Using a paintbrush, paint the top edge of the stack with padding compound. Wait for it to dry. Paint another coat.&lt;/p&gt;

&lt;p&gt;If you have random loose paper, padding compound is also handy for recycling it into notepads.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;7. Mount it&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;This is not really needed, but is a nice touch. Find an old stand for a page-a-day calendar. Glue the cardboard backing in.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I hereby place the LaTeX template and LaTeX snippets in this post into the public domain.&lt;/em&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6724041043570642640?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6724041043570642640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/06/making-your-own-page-day-calendar.html#comment-form' title='13 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6724041043570642640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6724041043570642640'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/06/making-your-own-page-day-calendar.html' title='Making your own page-a-day calendar'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/_egN-3IJO0Xg/Sjw9BP0hN0I/AAAAAAAABW8/04mBWBEpTzE/s72-c/page.png' height='72' width='72'/><thr:total>13</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6359351567638019028</id><published>2009-06-14T20:35:00.000-07:00</published><updated>2009-06-14T20:42:00.447-07:00</updated><title type='text'>A different approach to fighting phishing</title><content type='html'>&lt;p&gt;We are usually advised to avoid being phished by looking carefully at the address bar for discrepancies. Unfortunately,&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;The web page; the URL; the SSL certificate (if any); indeed, all information displayed to the user; is information chosen by the attacker. The user is then asked to discover discrepancies in information that has been carefully designed for deception. This type of game is better suited to a book of puzzles than a secure user interface. &amp;mdash;&lt;a href="http://www.w3.org/2005/Security/usability-ws/papers/02-hp-petname/"&gt;Tyler Close&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;The problem is that humans are notoriously bad at detecting rare and non-obvious events.&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://www.waterken.com/user/PetnameTool/"&gt;Petname tool&lt;/a&gt; is a nifty alternative way to detect and expose phishing. It's a Firefox extension that lets you enter short messages (e.g. "stock trades") to be associated with a site's CA public key and distinguished name (DN). Those messages are only subsequently displayed to you when you return to the site if the key and DN match.&lt;/p&gt;
&lt;p&gt;This is somewhat similar to the approach used in SSH. That is, on the second and subsequent transactions between you and another party, it's not quite as valuable for you to know simply whether some trusted CA will vouch for that party. What you really want to know is that you are talking to &lt;em&gt;the same party&lt;/em&gt; you were talking to last time. (As with SSH, man-in-the-middle attacks on the second and subsequent logins can be detected... even if the user didn't properly verify the authenticity of the remote party on the first login!)&lt;/p&gt;
&lt;p&gt;Of course, all this is of little use if the human doesn't check the petname before entering his password. For that, the author suggests that web browsers be made to automatically manage credentials on our behalf...&lt;/p&gt;
&lt;p&gt;Further reading: &lt;a href="http://www.w3.org/2005/Security/usability-ws/papers/02-hp-petname/"&gt;W3C workshop paper&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6359351567638019028?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6359351567638019028/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/06/different-approach-to-fighting-phishing.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6359351567638019028'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6359351567638019028'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/06/different-approach-to-fighting-phishing.html' title='A different approach to fighting phishing'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2296126586470262188</id><published>2009-06-03T21:16:00.000-07:00</published><updated>2009-06-03T21:24:54.717-07:00</updated><title type='text'>Chrome is blazing</title><content type='html'>&lt;p&gt;I've been using the &lt;a href="https://launchpad.net/~chromium-daily/+archive/ppa"&gt;Chromium builds&lt;/a&gt; off and on for some time now and finally changed my default browser to Chromium. The two major reasons that sold me:&lt;/p&gt;
&lt;p&gt;One. It is &lt;em&gt;blazing&lt;/em&gt;. In comparison, Firefox 3.5 is now intolerably slow. I don't even want to try Firefox 3.0. This is both for rendering time and startup time. (Startup from a cold cache: 1 sec for Chromium, 10 sec for Firefox. That's right, Chromium loads in one second &lt;em&gt;on my 8 year-old computer&lt;/em&gt;.)&lt;/p&gt;
&lt;p&gt;Two. The "omnibox" (the unified area for selecting URLs, searches, and bookmarks). It works fantastically. Now, Firefox's implementation (the "awesomebar") is pretty admirable. They too support searching bookmarks and history and have a fairly sophisticated filtering language for narrowing the suggestions. But, as far as I can tell, in order to actually &lt;em&gt;use any of the suggestions&lt;/em&gt; you have to move your hands &lt;em&gt;away from the home row, down to the arrow keys&lt;/em&gt; to press "Down".&lt;/p&gt;
&lt;p&gt;From a UI perspective, this is snatching defeat from the jaws of victory. (In Chromium, pressing Enter in the omnibox selects the first completion.)&lt;/p&gt;
&lt;p&gt;Chromium is still a no-frills browser, and I still miss some Firefox extensions (okay, okay, only &lt;a href="http://psung.blogspot.com/2009/05/using-itsalltext-with-emacsemacsclient.html"&gt;one&lt;/a&gt;). But it's already good enough that using Firefox regularly is just unbearable now. Hats off to the Chromium engineers!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2296126586470262188?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2296126586470262188/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/06/chrome-is-blazing.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2296126586470262188'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2296126586470262188'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/06/chrome-is-blazing.html' title='Chrome is blazing'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4926633112523112265</id><published>2009-05-24T21:37:00.000-07:00</published><updated>2011-09-07T19:41:15.362-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='LaTeX'/><title type='text'>Making gorgeous LaTeX plots with Octave</title><content type='html'>&lt;p&gt;I &lt;a href="http://psung.blogspot.com/2007/03/gnuplot-plots-in-latex.html"&gt;previously&lt;/a&gt;
  wrote about using the &lt;tt&gt;epslatex&lt;/tt&gt; terminal in Gnuplot to generate
  beautiful plots for inclusion in a LaTeX document. The secret is that
  the &lt;tt&gt;epslatex&lt;/tt&gt; terminal produces a combination of (1) EPS vector
  graphics and (2) TeX instructions to overlay all the text (axis labels,
  legends, etc.) in whatever font you are using in the rest of your document.
  So typically you get that super slick looking Computer Modern Roman
  (cmr) font.&lt;/p&gt;
&lt;p&gt;Now, there are some things that are beyond the ken of Gnuplot. So it was a
  relief when I learned that &lt;a href="http://www.gnu.org/software/octave/"&gt;GNU
  Octave&lt;/a&gt; can produce similarly formatted EPS + TeX graphics. What's nice
  about using Octave instead of Gnuplot is that, not only can you take
  advantage of Octave's more advanced (as I understand it) graphics facilities,
  but you can also bring to bear all the power of a full
  mathematical/simulation language for preprocessing your data or whatnot. I
  still usually use Gnuplot, but I break out Octave for making plots when
  necessary.&lt;/p&gt;
&lt;p&gt;All you have to do is produce your plot in Octave as normal
  (e.g. &lt;tt&gt;plot(...)&lt;/tt&gt;), and use a command like the following to output in
  EPS + Tex:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;print('my_plot.tex', '-dtex');&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;As an example, here's some minimal code to produce a heatmap with
  contours and a legend:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;x_values = [0.10 : 0.005 : 0.60];
y_values = [0.10 : 0.005 : 0.60];
contourf(x_values, y_values, data); % supply your own data...
axis square;
colorbar;
xlim([0.1 0.6]);
ylim([0.1 0.6]);
print('-dtex', 'my_plot.tex');&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;img src="http://lh5.ggpht.com/_egN-3IJO0Xg/Shok7rg4vBI/AAAAAAAABQM/y5BrNFvoAjI/latex-heatmap.png"&gt;&lt;/p&gt;
&lt;p&gt;Octave really saves the day here. To the best of my knowledge it is
  difficult or impossible to do this using just plain Gnuplot, especially if
  you are not plotting over a square area.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4926633112523112265?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4926633112523112265/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/05/making-gorgeous-latex-plots-with-octave.html#comment-form' title='9 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4926633112523112265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4926633112523112265'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/05/making-gorgeous-latex-plots-with-octave.html' title='Making gorgeous LaTeX plots with Octave'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_egN-3IJO0Xg/Shok7rg4vBI/AAAAAAAABQM/y5BrNFvoAjI/s72-c/latex-heatmap.png' height='72' width='72'/><thr:total>9</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-8271875956659618362</id><published>2009-05-24T13:22:00.000-07:00</published><updated>2009-05-24T16:11:11.400-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Using itsalltext with emacs/emacsclient</title><content type='html'>&lt;p&gt;I finally started
  using &lt;a href="https://addons.mozilla.org/en-US/firefox/addon/4125"&gt;It's All
  Text!&lt;/a&gt;&amp;mdash; this is something I should done long ago. (It's All Text! is
  a Firefox extension that lets you invoke an external editor to edit the
  contents of any &lt;tt&gt;textarea&lt;/tt&gt; element, like this blog post I'm writing
  right now in Blogger.)&lt;/p&gt;
&lt;p&gt;There's such a stark contrast between using Emacs, where I feel at one with
  the document, and typing in the browser textarea, which always makes me feel
  kind of claustrophobic now (the problem is not that the textbox is too small,
  but that it doesn't provide enough degrees of freedom for editing).&lt;/p&gt;
&lt;p&gt;If you are using an Emacs with multi-TTY support (a v23 snapshot), you can
  leave one long-lived Emacs server instance running and quickly pop up a new
  frame from it for each editing buffer:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;From your main Emacs frame, run &lt;tt&gt;M-x server-start&lt;/tt&gt;.&lt;/li&gt;
  &lt;li&gt;Save the following wrapper script (I called mine &lt;tt&gt;ecw&lt;/tt&gt;) and
    configure it to be your editor in It's All Text!:
    &lt;blockquote&gt;&lt;pre&gt;#!/bin/sh
/usr/bin/emacsclient -c $@&lt;/pre&gt;&lt;/blockquote&gt;&lt;/li&gt;
  &lt;li&gt;In the It's All Text! options you can configure your favorite hotkey to
    launch a new Emacs frame for editing.&lt;/li&gt;
  &lt;li&gt;When you're done with a buffer, save and press &lt;tt&gt;C-x #&lt;/tt&gt; to return
    to Firefox.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; another tip. To automatically fire up &lt;tt&gt;html-mode&lt;/tt&gt; when
  editing text from, say, &lt;tt&gt;blogger.com&lt;/tt&gt;, you can add something like this
  to your &lt;tt&gt;.emacs&lt;/tt&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;tt&gt;(add-to-list 'auto-mode-alist '("/www\\.blogger\\.com\\.[^/]+\\.txt\\'" . html-mode))&lt;/tt&gt;&lt;/blockquote&gt;
&lt;p&gt;This works because the temp file that It's All Text! creates has a name
  like &lt;tt&gt;www.blogger.com.2a2q1e2r32.txt&lt;/tt&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-8271875956659618362?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/8271875956659618362/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/05/using-itsalltext-with-emacsemacsclient.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8271875956659618362'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8271875956659618362'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/05/using-itsalltext-with-emacsemacsclient.html' title='Using itsalltext with emacs/emacsclient'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2703106661087878239</id><published>2009-04-30T22:34:00.000-07:00</published><updated>2009-04-30T22:57:43.012-07:00</updated><title type='text'>Clever software names</title><content type='html'>&lt;p&gt;Many free software projects have, among other characteristics, punny project names. Some notable examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GNU &lt;a href="http://www.gnu.org/software/cssc/"&gt;CSSC&lt;/a&gt; (Compatibly Stupid Source Control), a clone of the Unix source control system SCCS (Source Code Control System).&lt;/li&gt;
&lt;li&gt;&lt;a href="http://gnupg.org/"&gt;GPG&lt;/a&gt; (GNU Privacy Guard), a clone of Phil Zimmerman's encryption program PGP (Pretty Good Privacy)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I suspect that people would think twice about choosing those names if those products were invented today. Naming a similar product (a clone, even) with a name that is &lt;em&gt;intentionally&lt;/em&gt; confusingly similar seems, indeed, like the &lt;em&gt;perfect&lt;/em&gt; way to get yourself slapped with a trademark lawsuit. (After all, it happened to Lindows.)&lt;/p&gt;
&lt;p&gt;At least GNU is safe. No reasonable person would think that &lt;em&gt;GNU's Not Unix&lt;/em&gt; was the same as Unix.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2703106661087878239?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2703106661087878239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/04/clever-software-names.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2703106661087878239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2703106661087878239'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/04/clever-software-names.html' title='Clever software names'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7722834043343300811</id><published>2009-04-10T00:41:00.000-07:00</published><updated>2010-08-25T12:07:36.973-07:00</updated><title type='text'>Microsoft Excel is a creation of staggering boneheadedness</title><content type='html'>&lt;p&gt;What I learned about Microsoft Excel today makes me not really want to use it again for anything that is even moderately important.&lt;/p&gt;
&lt;p&gt;Did you know that there is no easy way to import data into Excel with any fidelity?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Just write to a delimited file&lt;/em&gt;, you say. CSV data, TSV data, whatever... they are all very easy to produce programmatically. And they will &lt;em&gt;all&lt;/em&gt; get screwed up when you open them.&lt;/p&gt;
&lt;p&gt;You see, when you open such a file, one of two things will happen, both of them bad.&lt;/p&gt;
&lt;p&gt;First, Excel may open the file without complaint. I think this happens when you double-click on the file in Windows. Excel will then apply heuristics to set the format for each cell appropriately. These heuristics are not 100% reliable, for which I can hardly fault Excel. As one example, a cell containing a list of numbers &lt;tt&gt;50001,50002,50003,50014,50018&lt;/tt&gt; is interpreted as a single large integer, which Excel converts to the floating-point number &lt;tt&gt;5.00e24&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;However, and here is the problem, the conversions are silent (no warning is given upon opening a CSV file) and lossy (above, some of the precision needed to construct the original sequence is lost), and they cannot be reverted by any magic incantations within Excel after you've opened the spreadsheet.&lt;/p&gt;
&lt;p&gt;That's right. When opening CSV/TSV files, &lt;b&gt;Microsoft Excel's default behavior is to silently corrupt your data.&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;I'm running into this problem at work, and I'm just glad that someone noticed what was wrong, because this is really pernicious. You might spot-check your spreadsheet and think that everything is fine and not notice that your data is corrupted starting in row 8000. This is actually happening &lt;a href="http://www.pubmedcentral.nih.gov/articlerender.fcgi?tool=pubmed&amp;pubmedid=15214961"&gt;in biomedical research&lt;/a&gt;. Gene names, identifiers, you name it&amp;mdash; are silently and irreparably converted to numbers and dates in Excel. (And those researchers don't believe there's any good way to deal with this either.)&lt;/p&gt;
&lt;p&gt;For the record, OpenOffice gets this right, by preserving data verbatim by default when importing. That is positively brilliant in comparison.&lt;/p&gt;
&lt;p&gt;Now, the second thing that might have happened when you opened your file in Excel is that you invoke Excel's "Import Wizard." I think this happens when you choose "File" "Open" and select a delimited file. Excel will dutifully ask you how the columns are to be delimited and what format to use for each column.&lt;/p&gt;
&lt;p&gt;And, although you can select "Text" format here (meaning, preserve the input verbatim), the default format is the "do what Excel thinks is best" option. &lt;b&gt;Once again, Microsoft Excel's default behavior is to corrupt your data.&lt;/b&gt; Sure, in this case at least you can click on each column you think might have a problem and select "Text" format for it. But if you are a human, and you're opening these kinds of files all the time, and you trust yourself to do this consistently and correctly, you probably deserve what's coming to you. Humans are not good at performing repetitive tasks. That's supposed to be the &lt;em&gt;computer's&lt;/em&gt; job.&lt;/p&gt;
&lt;p&gt;What are we expected to do, write out Excel's XML-based file format directly, now that's it's nominally "open" and "documented"? That seems really heavyweight. It is kind of a remarkable oversight that it is so difficult to massage arbitrary data into any format that can be reliably read by Excel.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7722834043343300811?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7722834043343300811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/04/microsoft-excel-is-creation-of.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7722834043343300811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7722834043343300811'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/04/microsoft-excel-is-creation-of.html' title='Microsoft Excel is a creation of staggering boneheadedness'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-100027990603286615</id><published>2009-04-08T21:15:00.000-07:00</published><updated>2010-09-29T22:09:07.235-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Extracting select pages from a PDF</title><content type='html'>&lt;p&gt;Ever needed to make a new PDF containing a subset of the pages of an existing PDF?&lt;/p&gt;
&lt;p&gt;The &lt;tt&gt;pdfnup&lt;/tt&gt; tool is nominally for printing PDFs &lt;em&gt;n&lt;/em&gt;-up (&lt;em&gt;n&lt;/em&gt; logical pages to a sheet), but it can be told to cut and paste pages into a new PDF, like so:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;&lt;b&gt;pdfnup original.pdf --nup 1x1 --pages 1,3,5,7,21-25 --outfile subset.pdf&lt;/b&gt;&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;On Ubuntu, you can install &lt;tt&gt;pdfnup&lt;/tt&gt; with a simple &lt;tt&gt;sudo aptitude install pdfjam&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Further reading: &lt;a href="http://www2.warwick.ac.uk/fac/sci/statistics/staff/academic/firth/software/pdfjam/"&gt;&lt;tt&gt;pdfjam&lt;/tt&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; &lt;tt&gt;&lt;a href="http://www.pdfhacks.com/pdftk/"&gt;pdftk&lt;/a&gt;&lt;/tt&gt; also seems like an intriguing option, especially for more complex operations.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-100027990603286615?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/100027990603286615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/04/extracting-select-pages-from-pdf.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/100027990603286615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/100027990603286615'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/04/extracting-select-pages-from-pdf.html' title='Extracting select pages from a PDF'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7974072116925382496</id><published>2009-04-02T23:29:00.000-07:00</published><updated>2009-04-03T00:08:13.506-07:00</updated><title type='text'>Toto, I've a feeling we're not in 32-bit land anymore</title><content type='html'>&lt;p&gt;I got a new computer and have had some time to put it through its paces. It's a Dell Studio XPS, with a Core i7 920, 6GB of RAM, and a 24" display. All things considered it was a pretty good deal (ordered in January, $1060 shipped). I later upgraded to 2TB of disk.&lt;/p&gt;
&lt;p&gt;This thing is &lt;em&gt;blazing&lt;/em&gt;. And building with &lt;tt&gt;make -j8&lt;/tt&gt; makes me happy inside.&lt;/p&gt;
&lt;p&gt;As far as I can tell, everything in it works out of the box with all free software on Ubuntu GNU/Linux Jaunty Jackalope (9.04) x86_64. (Even the ATI Mobility Radeon HD 3450.)&lt;/p&gt;
&lt;p&gt;The display, a Dell S2409W, is nothing to sneeze at, either.&lt;/p&gt;
&lt;p&gt;There is space inside the case to mount an extra hard drive. It goes in vertically, which is nice because you don't have to wrestle with all the cables and wedge it past the RAM to get it in. However, there is only space for &lt;em&gt;one&lt;/em&gt; additional hard drive.&lt;/p&gt;
&lt;p&gt;Power consumption is much better than my old desktop. The machine idles at 97W. This goes up to maybe 170W at high load.&lt;/p&gt;
&lt;p&gt;My only complaint is the noise. The fans go on like a leafblower when you're pegging the CPU, but I don't really care about that part. The problem for me is more the baseline noise. The computer isn't loud, per se... but it isn't quiet either. It's in my room and I put on earplugs when I go to sleep. Take that with a grain of salt, though, because I'm a person who has trouble falling asleep in the presence of a wall clock.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7974072116925382496?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7974072116925382496/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/04/toto-ive-feeling-were-not-in-32-bit.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7974072116925382496'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7974072116925382496'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/04/toto-ive-feeling-were-not-in-32-bit.html' title='Toto, I&apos;ve a feeling we&apos;re not in 32-bit land anymore'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5177272383511583885</id><published>2009-03-09T21:19:00.000-07:00</published><updated>2009-03-30T21:57:27.526-07:00</updated><title type='text'>Chrome</title><content type='html'>&lt;p&gt;I haven't used Google Chrome much, but it's been interesting following Chrome/Chromium development &lt;a href="http://ponderer.org/"&gt;on&lt;/a&gt; &lt;a href="http://neugierig.org/software/chromium/notes/"&gt;the&lt;/a&gt; &lt;a href="http://blog.chromium.org/"&gt;blogs&lt;/a&gt;. The things that make it to the blogs are neither too vague so as to be uninteresting nor too detailed so as to seem unimportant or trivial.&lt;/p&gt;
&lt;p&gt;The Chrome folks have a lot of cool ideas (especially about UI), and it's neat seeing fresh ideas in the web browser arena. One of my favorite little gems so far:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;In most tab strips, when you close a tab the other tabs expand to fit the space that has just been made available. The upshot of this is that the close boxes of the remaining tabs all move around slightly, which makes it harder to quickly close tabs by clicking in the same spot. [...]&lt;/p&gt;
&lt;p&gt;For Chrome, we came up with something a little different. Realizing that maintaining a fixed width for tabs when closing them would keep close buttons aligned under the mouse pointer, we designed a system whereby the tab strip will re-layout when you close a tab to fill the gap left, but not resize the remaining tabs, until you move your mouse away from the tab strip [...].&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;(Ben Goodger, &lt;a href="http://blog.chromium.org/2009/01/tabbed-browsing-in-google-chrome.html"&gt;"Tabbed Browsing in Google Chrome"&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;That is clever. An engineer did the right thing there.&lt;/p&gt;
&lt;p&gt;In addition, it's interesting to be able to read about the software development methodology employed by Google, which one usually doesn't hear too much about. For example, the way they use usage data to &lt;a href="http://blog.chromium.org/2009/02/spell-check-dictionary-improvements.html"&gt;identify newly coined words that should be added to the spellcheck dictionaries&lt;/a&gt; or the way they systematically &lt;a href="http://www.google.com/googlebooks/chrome/small_08.html"&gt;regression-test the renderer on the million most popular web sites&lt;/a&gt;. Most free software projects don't have these resources, and most proprietary shops don't publicize these kinds of details.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Update, 30 Mar 2009:&lt;/b&gt; I tried some Chromium builds on GNU/Linux and they are &lt;em&gt;blazing&lt;/em&gt;. Wow.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5177272383511583885?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5177272383511583885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/03/chrome.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5177272383511583885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5177272383511583885'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/03/chrome.html' title='Chrome'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-8149465022172906029</id><published>2009-02-28T01:34:00.000-08:00</published><updated>2010-09-29T22:09:07.235-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Configuring Radeon R600/R700 devices on Ubuntu Jaunty</title><content type='html'>&lt;p&gt;&lt;b&gt;Update, 18 Mar 2009&lt;/b&gt;: Ubuntu Jaunty Jackalope 9.04 and later now support R600/R700 hardware out of the box. Make sure you update to at least xserver-xorg-video-radeon 1:6.12.1-0ubuntu1, libdrm2 2.4.5-0ubuntu2, and linux-image-generic 2.6.28.11.11. If you have done so, &lt;b&gt;you can stop reading this page now&lt;/b&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Update, 5 Mar 2009&lt;/b&gt;: fixed the instructions for the DRM modules. You need to build from the &lt;tt&gt;origin/r6xx-r7xx-support&lt;/tt&gt; branch.&lt;/p&gt;
&lt;p&gt;I got a new computer with an ATI Radeon 3450 graphics card (R600 series). Here are the steps I took to configure it on Ubuntu Jaunty Jackalope 9.04 using free software (open source) drivers. The instructions below might also be useful for other Radeon hardware, in particular, R700-series cards.&lt;/p&gt;
&lt;p&gt;Happily, Ubuntu 9.04 does drive the 3450 out-of-the-box (it boots into X and is usable, using the free &lt;tt&gt;radeon&lt;/tt&gt; driver). Its performance was, however, kind of poor on my machine. I noticed "wiping" and flickering when scrolling (e.g. in firefox or gnome-terminal) or moving windows around.&lt;/p&gt;
&lt;p&gt;Building the development versions of the &lt;tt&gt;radeonhd&lt;/tt&gt; and &lt;tt&gt;drm&lt;/tt&gt; drivers fixed these issues and significantly improved desktop performance. Everything is quite slick-looking now, even while driving a 1900x1080 display. Kudos to the driver developers, and to AMD/ATI for cooperating with driver development. Ubuntu does package &lt;tt&gt;radeonhd&lt;/tt&gt;, so sooner or later, after this code gets released, an out-of-the-box installation will provide this level of performance as well.&lt;/p&gt;
&lt;p&gt;For historical reasons there are two free drivers for ATI Radeon devices: &lt;tt&gt;radeon&lt;/tt&gt; and &lt;tt&gt;radeonhd&lt;/tt&gt;. They have approximate feature-parity these days. I used &lt;tt&gt;radeonhd&lt;/tt&gt; because I found instructions for it first. :) Instructions are adapted from these sources: &lt;a href="http://wiki.x.org/wiki/radeonhd%3Ar6xx_r7xx_branch"&gt;radeonhd r600-r700 instructions&lt;/a&gt;, &lt;a href="https://help.ubuntu.com/community/RadeonHD"&gt;Ubuntu community documentation for RadeonHD&lt;/a&gt;. (For your reference, the &lt;a href="http://wiki.x.org/wiki/RadeonFeature"&gt;Radeon feature matrix&lt;/a&gt; describes what features are supported on what models.)&lt;/p&gt;
&lt;p&gt;Download the build prerequisites:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$ sudo aptitude install git-core build-essential
$ sudo aptitude build-dep xserver-xorg-video-radeonhd&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Clone the repos for &lt;tt&gt;radeonhd&lt;/tt&gt; and &lt;tt&gt;drm&lt;/tt&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$ git clone git://anongit.freedesktop.org/git/xorg/driver/xf86-video-radeonhd
$ git clone git://anongit.freedesktop.org/mesa/drm&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Build and install &lt;tt&gt;radeonhd&lt;/tt&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$ cd xf86-video-radeonhd
$ ./autogen.sh --prefix=/usr
$ make
$ sudo make install
$ cd ..&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Build and install the &lt;tt&gt;drm&lt;/tt&gt; modules:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;$ cd drm/linux-core
$ git checkout origin/r6xx-r7xx-support
$ make radeon.o drm.o
$ sudo cp radeon.ko /lib/modules/`uname -r`/kernel/drivers/gpu/drm/radeon/
$ sudo cp drm.ko /lib/modules/`uname -r`/kernel/drivers/gpu/drm/&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Now we'll configure X to use the new drivers. If you don't have an &lt;tt&gt;xorg.conf&lt;/tt&gt; file with stuff in it, auto-generate one:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;# X -configure
# mv /root/xorg.conf.new /etc/X11/xorg.conf&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Change the &lt;tt&gt;Device&lt;/tt&gt; section. I modified the &lt;tt&gt;Driver&lt;/tt&gt; line and added the following options:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;Section "Device"
    Driver "radeonhd"
    Option "AccelMethod" "exa"
    Option "DRI" "on"
    Option "VideoOverlay" "off"
    Option "OpenGLOverlay" "on"
    Option "TexturedVideo" "off"
    [...]
EndSection&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Verify that the DRI module is loaded and that non-root applications can access it:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;Section "Module"
    Load  "dri"
    [...]
EndSection

Section "DRI"
    Mode 0666
EndSection
&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Then reboot your computer. That should do it.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-8149465022172906029?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/8149465022172906029/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/02/configuring-radeon-r600r700-devices-on.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8149465022172906029'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8149465022172906029'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/02/configuring-radeon-r600r700-devices-on.html' title='Configuring Radeon R600/R700 devices on Ubuntu Jaunty'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2632863233743407833</id><published>2009-02-16T00:45:00.000-08:00</published><updated>2009-02-16T00:53:34.841-08:00</updated><title type='text'>2008 in Review</title><content type='html'>&lt;p&gt;I know, it's a month and a half into 2009, but... well, better late than never.&lt;/p&gt;
&lt;p&gt;The following is a list of the most popular posts on this blog and on my web site in 2008. Numbers 1, 3, and 5 hit Reddit. People mostly found the other articles by searching.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="http://web.psung.name/emacstips/topten.html"&gt;Top Ten Essential Emacs Tips&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://psung.blogspot.com/2008/09/scrolling-with-thinkpads-trackpoint-in.html"&gt;Scrolling with the Thinkpad's TrackPoint in Ubuntu 8.10 Intrepid&lt;/a&gt;. Who knew a little X.org tweak could cause so much trouble?&lt;/li&gt;
&lt;li&gt;&lt;a href="http://psung.blogspot.com/2008/06/million-lines-of-lisp.html"&gt;A million lines of Lisp&lt;/a&gt;. Apparently, people will read &lt;em&gt;anything&lt;/em&gt; about Lisp.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://psung.blogspot.com/2008/03/emacs-in-ubuntu-hardy-now-has-anti.html"&gt;Emacs in Ubuntu Hardy now has anti-aliased fonts&lt;/a&gt;. And it is beautiful.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://psung.blogspot.com/2008/10/stupid-screen-tricks.html"&gt;Stupid screen tricks&lt;/a&gt;. GNU Screen has changed the way I work and the way I interact with computers.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://web.psung.name/emacs/setup.html"&gt;Instructions for setting up Emacs on a variety of platforms&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://psung.blogspot.com/2008/07/towards-using-freerunner-as-my-primary.html"&gt;Towards using the FreeRunner as my primary phone&lt;/a&gt;. Which, I am happy to say, I have been now for months.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://web.psung.name/raytracer/"&gt;Writing a raytracer from scratch&lt;/a&gt;. Why, you ask? Why the hell not? It was a lot of fun and I learned a thing or two about software and math.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;(Google Analytics helped me make this list. Interesting tidbit: among the browsers that people typically use to read this blog, Firefox has a commanding lead with 75%. The runner-up is Safari with 7%, followed by IE with 5%.)&lt;/p&gt;
&lt;p&gt;Highlights of the past year:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I wrote a thesis and got some &lt;a href="http://web.psung.name/#publications"&gt;papers&lt;/a&gt; published. In the course of my work, I also learned a few things about software development and tools, which I'll share shortly.&lt;/li&gt;
&lt;li&gt;I traveled to New York, Las Vegas, Germany, and Switzerland (with passage through Spain, Liechtenstein, Austria, and the UK). All of these were a lot of fun.&lt;/li&gt;
&lt;li&gt;I got a &lt;a href="http://openmoko.com/"&gt;new phone&lt;/a&gt; (some would say, a mobile computer with a phone &lt;em&gt;in it&lt;/em&gt;), one capable of running only free software. It's glorious.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;2008 was a great year. Except for the collapse of the global economy, but remember, now is the time to buy. Here's to 2009!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2632863233743407833?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2632863233743407833/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/02/2008-in-review.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2632863233743407833'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2632863233743407833'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/02/2008-in-review.html' title='2008 in Review'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2389109418715279284</id><published>2009-01-31T22:17:00.000-08:00</published><updated>2010-09-29T22:09:07.236-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>The Ubuntu netboot/network installers</title><content type='html'>&lt;p&gt;The Ubuntu netboot (network) installers are fantastic, and for how good they are, they are hardly ever publicized.&lt;/p&gt;
&lt;p&gt;The idea of just downloading your OS whenever and wherever you need to install it is kind of astounding. It makes the Windows/Mac experience of having to dig up some DVD and type in a 25-digit number seem positively archaic. It's the difference between walking across the street to buy bottled water, and turning on the tap and just having water appear. It completely changes the economics of the game when you no longer have to think of your operating system as a scarce resource.&lt;/p&gt;
&lt;p&gt;As I understand it, there are three ways to do a netboot install. I've previously written about &lt;a href="http://psung.blogspot.com/2008/06/installing-ubuntu-from-hard-disk-grub.html"&gt;installing Ubuntu by booting from files downloaded to your hard disk&lt;/a&gt;. It's also easy to do a netboot install from either a CD or a USB key, and the procedures are very similar.&lt;/p&gt;
&lt;p&gt;All three methods are nice because they have small initial downloads, about 10 MB; they then download the rest of your OS (and only the latest version of each package) at install time. It's a waste of time to download a ~700MB CD image if you're going to upgrade half of your packages right after installation. (Software is usually out of date by the time you install it! Especially during the development period for each release.) The installer is small enough that you can even burn it to one of those business card CDs.&lt;/p&gt;
&lt;p&gt;The netboot installers are also versatile. They will install, at your request, any (or all!) of the following: Ubuntu desktop, Ubuntu server, Kubuntu desktop, Xubuntu desktop, Edubuntu desktop, and many more. They also support installing to encrypted LVM for full-disk encryption. (The netboot installers are based on the ncurses Debian installer.)&lt;/p&gt;
&lt;p&gt;The hard disk method has the advantage that, of course, you don't need to use any external media. However, in my experience, the CD and USB key installers are a little less flaky. Unlike a hard disk installation, they also work even if you don't have Grub already installed.&lt;/p&gt;
&lt;p&gt;For either the CD or USB key methods, you can find the appropriate files here:&lt;/p&gt;
&lt;p&gt;&lt;tt&gt;&lt;a href="http://archive.ubuntu.com/ubuntu/dists/jaunty/main/installer-i386/current/images/netboot/"&gt;http://archive.ubuntu.com/ubuntu/dists/jaunty/main/installer-i386/current/images/netboot/&lt;/a&gt;&lt;/tt&gt;&lt;/p&gt;
&lt;p&gt;(This is for Jaunty/i386. If you want a different release or have a different architecture, like &lt;tt&gt;amd64&lt;/tt&gt;, adjust the URL accordingly.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;For CD installation&lt;/b&gt;: download &lt;tt&gt;mini.iso&lt;/tt&gt; and burn it to your CD.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;For USB media installation&lt;/b&gt;: download &lt;tt&gt;boot.img.gz&lt;/tt&gt; and &lt;a href="https://help.ubuntu.com/8.04/installation-guide/i386/boot-usb-files.html"&gt;follow the instructions here&lt;/a&gt;. It will boil down to doing something like this:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;# zcat boot.img.gz &amp;gt; /dev/sdX1&lt;br&gt;# aptitude install mbr&lt;br&gt;# install-mbr /dev/sdX&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Then boot from your new media into the installer.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2389109418715279284?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2389109418715279284/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/01/ubuntu-netboot-installers.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2389109418715279284'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2389109418715279284'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/01/ubuntu-netboot-installers.html' title='The Ubuntu netboot/network installers'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7259792966606529519</id><published>2009-01-31T00:00:00.002-08:00</published><updated>2009-01-31T00:21:39.962-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>"Being Productive With Emacs" Redux</title><content type='html'>&lt;p&gt;This past &lt;a href="http://web.mit.edu/iap/"&gt;IAP&lt;/a&gt; I taught a short class on Emacs ("Being Productive With Emacs") at MIT. It was similar in content to the class that I taught in 2007, although I pared down the material a bit.&lt;/p&gt;
&lt;p&gt;I've posted the &lt;a href="http://web.psung.name/emacs/"&gt;slides&lt;/a&gt; online. You may use the slides under the terms of the GFDLv1.3+ or the GPLv3+.&lt;/p&gt;
&lt;p&gt;(I made the slides using &lt;a href="http://meyerweb.com/eric/tools/s5/"&gt;S5&lt;/a&gt;, which is pretty sweet. It lets you make moderately professional looking DHTML slides in a text editor without much pain.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7259792966606529519?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7259792966606529519/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/01/being-productive-with-emacs-redux.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7259792966606529519'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7259792966606529519'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/01/being-productive-with-emacs-redux.html' title='&quot;Being Productive With Emacs&quot; Redux'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5820900620689278583</id><published>2009-01-24T20:12:00.004-08:00</published><updated>2009-01-24T20:32:50.980-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>A command-line substitute for gitk</title><content type='html'>&lt;p&gt;&lt;tt&gt;gitk&lt;/tt&gt; is indispensable for viewing repo histories and understanding the relationships between different branches. However, using a GUI is a bit heavyweight if you are working remotely or only need to see the last few commits. Under these circumstances, &lt;tt&gt;git log --graph&lt;/tt&gt;, introduced in git 1.5.6, is a pretty good fake.&lt;/p&gt;
&lt;p&gt;My preferred invocation is&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;git log --graph --abbrev-commit --pretty=oneline --decorate&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;which I've aliased to &lt;tt&gt;gl&lt;/tt&gt; in my shell.&lt;/p&gt;
&lt;p&gt;The subsequent options, respectively: only show short commit names, for compactness; only display one line per commit, for compactness; and show where your branches are. Here's some sample output:&lt;/p&gt;
&lt;pre&gt;* f95f34e... (refs/remotes/origin/master, refs/heads/master) Acknowledge Alexey.
* c691bc7... Allow unmarking the marked commit.
* 7640638... Fixed visualization of marked commits
* c3830ed... Make it work better on Windows.  Thanks to Jeff Dik.
*   3433556... Merge commit 'fdr/sign-off'
|\  
| * 68344a2... Add signoff customization option
* |   3e29059... Merge commit 'cymacs/master'
|\ \  
| * | 45fb865... Fix incorrect diff hightlighting of lines beginning with "+" or "-".
| * | b7fe745... Disable undo in all magit-mode buffers.
| |/  
* | 10fe99a... Ambiguity in call to git log fixed
* | 3d34a7c... Make buffer saving behavior customizable.
* | 64b8265... Removed unused threshold machinery.
* | b430add... Make sure that point never ends up in an invisible region.
|/  
*   b30faeb... Merge commit 'voins/voins'
|\  
| * 7386af1... Use "medium" git log format when visiting commit
* | 5fb7327... Mention autogen.sh
* | f055b18... Typo.
|/  &lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5820900620689278583?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5820900620689278583/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/01/command-line-substitute-for-gitk.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5820900620689278583'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5820900620689278583'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/01/command-line-substitute-for-gitk.html' title='A command-line substitute for gitk'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-569734467071723090</id><published>2009-01-06T11:51:00.002-08:00</published><updated>2009-10-29T19:14:01.535-07:00</updated><title type='text'>One small step for freedom</title><content type='html'>&lt;p&gt;Today, Apple &lt;a href="http://www.apple.com/pr/library/2009/01/06itunes.html"&gt;announced&lt;/a&gt; that it is phasing out DRM in its music store. By the end of the quarter, Apple says that all songs in the iTunes music store will be DRM-free.&lt;/p&gt;
&lt;p&gt;This is good news.&lt;/p&gt;
&lt;p&gt;However, I hope that a victory for users in this battle does not lead people to believe that the war is over, or that DRM is just about music. Let's not pretend that this is the end of &lt;a href="http://en.wikipedia.org/wiki/App_Store"&gt;DRM at Apple&lt;/a&gt;. Let's not even pretend that this is the end of &lt;a href="http://en.wikipedia.org/wiki/ITunes_Store#Video"&gt;DRM&lt;/a&gt; &lt;a href="http://en.wikipedia.org/wiki/Digital_Audio_Access_Protocol#DAAP_authentication"&gt;in iTunes&lt;/a&gt;, as has been &lt;a href="http://blogs.zdnet.com/Burnette/?p=702"&gt;widely&lt;/a&gt; &lt;a href="http://i.gizmodo.com/5124588/itunes-gets-drm-free-new-prices-purchase-over-3g"&gt;and&lt;/a&gt; &lt;a href="http://www.macworld.com/article/137946/2009/01/itunestore.html"&gt;erroneously&lt;/a&gt; &lt;a href="http://technology.timesonline.co.uk/tol/news/tech_and_web/article5461500.ece"&gt;reported&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I'm not holding my breath, but if I have a shred of optimism about this whole situation, it's because &lt;a href="http://www.apple.com/hotnews/thoughtsonmusic/"&gt;Steve Jobs has publicly disparaged DRM in music&lt;/a&gt;. DRM elsewhere is no less pernicious.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-569734467071723090?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/569734467071723090/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/01/one-small-step-for-freedom.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/569734467071723090'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/569734467071723090'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/01/one-small-step-for-freedom.html' title='One small step for freedom'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2897307974493722314</id><published>2009-01-04T13:18:00.007-08:00</published><updated>2009-01-06T10:30:32.159-08:00</updated><title type='text'>Disabling Firefox's yellow plugin bar</title><content type='html'>&lt;p&gt;I hate Flash. But that is a rant for a different post.&lt;/p&gt;
&lt;p&gt;I don't have Flash installed, and I don't want to have Flash installed. That means I get Firefox's yellow "Additional plugins are required to display all the media on this page" informational bar on many pages with Flash content. Here are instructions for disabling it in Firefox on Ubuntu 8.10.&lt;/p&gt;
&lt;p&gt;[&lt;b&gt;Update&lt;/b&gt;: much easier way to do this, apparently available on Firefox 3.0+: in Firefox, simply go to &lt;tt&gt;about:config&lt;/tt&gt; and set &lt;tt&gt;plugins.hide_infobar_for_missing_plugin&lt;/tt&gt; to &lt;tt&gt;true&lt;/tt&gt;. Thanks, Rakhun!&lt;/p&gt;
&lt;p&gt;The more complicated way I originally suggested doing this follows.]&lt;/p&gt;
&lt;div style="color: #888"&gt;
&lt;p&gt;In Firefox, go to &lt;tt&gt;about:config&lt;/tt&gt; and set &lt;tt&gt;plugin.default_plugin_disabled&lt;/tt&gt; to &lt;tt&gt;false&lt;/tt&gt;. By itself, this suppresses the yellow plugin bar and replaces it with a dialog, which is even worse! In order to disable this dialog, you'll also need to delete the file &lt;tt&gt;/usr/lib/xulrunner-addons/plugins/libnullplugin.so&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;(The "null plugin" or "default plugin" is responsible for rendering a blank box and prompting you whenever Firefox encounters content it doesn't have another plugin for.)&lt;/p&gt;
&lt;p&gt;If you ever regret this decision, you could keep &lt;tt&gt;libnullplugin.so&lt;/tt&gt; somewhere safe and just move it back to that directory&amp;mdash;or, just reinstall &lt;tt&gt;xulrunner-1.9&lt;/tt&gt; with &lt;tt&gt;aptitude reinstall xulrunner-1.9&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;On other systems, you can identify the location of the default plugin by setting &lt;tt&gt;plugin.expose_full_path&lt;/tt&gt; to &lt;tt&gt;true&lt;/tt&gt;. Then go to &lt;tt&gt;about:plugins&lt;/tt&gt; and look for the "Default plugin". Firefox should show you the path to the plugin file. Delete that file.&lt;/p&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2897307974493722314?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2897307974493722314/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2009/01/disabling-firefoxs-yellow-plugin-bar.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2897307974493722314'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2897307974493722314'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2009/01/disabling-firefoxs-yellow-plugin-bar.html' title='Disabling Firefox&apos;s yellow plugin bar'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-5776291705287266229</id><published>2008-12-28T18:40:00.000-08:00</published><updated>2008-12-28T21:40:45.567-08:00</updated><title type='text'>A holiday plea</title><content type='html'>&lt;p&gt;Shortly before the holidays I made donations to three organizations: the &lt;a href="http://www.fsf.org/"&gt;Free Software Foundation&lt;/a&gt;, &lt;a href="http://wikipedia.org"&gt;Wikipedia&lt;/a&gt;, and &lt;a href="http://creativecommons.org/"&gt;Creative Commons&lt;/a&gt;. If you'll kindly indulge me for a minute, I'll explain why I think the work of these organizations is so important to an open internet and a free and properous society. Consider giving whatever you can spare (whenever you can spare it) to one of these groups.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1&lt;/b&gt;. So much of our everyday lives&amp;mdash;both work and play&amp;mdash;depends on the operation of software that we cannot really claim to be free people unless we are using free software. I'm donating to the &lt;b&gt;Free Software Foundation&lt;/b&gt; both as thanks for the GNU operating system and in support of their campaigns. The GNU OS&amp;mdash;from &lt;tt&gt;ls&lt;/tt&gt; to &lt;tt&gt;emacs&lt;/tt&gt;, and everything in between, and beyond&amp;mdash;eclipses, in terms of power and productivity, pretty much any other OS you can buy. But peace of mind is even more valuable than technical power. As someone whose livelihood directly depends on software, it would be foolish in the extreme for me to compromise my autonomy and financial security by using proprietary software and "giving the keys to someone else."&lt;/p&gt;
&lt;p&gt;The FSF also promotes awareness of a number of threats to freedom and innovation, like DRM (vile, vile stuff) and proprietary document formats (which are antithetical to the democratic idea of the free interchange of information).&lt;/p&gt;
&lt;p&gt;&lt;b&gt;2&lt;/b&gt;. I'd say that being able to learn about anything, anytime, on &lt;b&gt;Wikipedia&lt;/b&gt; has been a pretty life-changing experience. I don't need to explain what this is like to most of you. But Wikipedia isn't valuable just because it satisfies my idle curiosities. One of the hats I wear is that of "teacher," and I love sharing knowledge. The dissemination of knowledge is one of the surest ways to produce prosperity. I'm donating to Wikipedia on behalf of children and other curious people everywhere.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;3&lt;/b&gt;. &lt;b&gt;Creative Commons&lt;/b&gt; is creating a body of actually useful creative works, as well as encouraging people to rethink copyright law. I feel like I've discovered a gem every time I find an ebook I can copy for offline reading, or music I can share with friends, or a comic or photo that I can put on my blog. What is perhaps more valuable is that CC is planting the idea in people's heads that maybe we can be more prosperous as a society if authors allow their work to be used in more ways rather than fewer.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-5776291705287266229?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/5776291705287266229/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/12/holiday-plea.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5776291705287266229'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/5776291705287266229'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/12/holiday-plea.html' title='A holiday plea'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-8874621181071085708</id><published>2008-12-26T10:32:00.005-08:00</published><updated>2008-12-26T20:57:25.137-08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Magit</title><content type='html'>&lt;p&gt;&lt;a href="http://zagadka.vm.bytemark.co.uk/magit/"&gt;Magit&lt;/a&gt; is a spectacular Emacs add-on for interacting with git. Magit was designed with git in mind (unlike VC mode, which is a more generic utility), so git commands map quite straightforwardly onto Magit commands. &lt;tt&gt;M-x magit-status&lt;/tt&gt; tells you about the current state of your repo and gives you one-key access to many common git commands. However, what really sold me on Magit was its patch editor, which completely obsoletes my use of &lt;tt&gt;git&amp;nbsp;add&lt;/tt&gt;, &lt;tt&gt;git&amp;nbsp;add&amp;nbsp;--interactive&lt;/tt&gt;, and &lt;tt&gt;git&amp;nbsp;add&amp;nbsp;--patch&lt;/tt&gt;. If Magit had this patch editor and nothing else, I would still use it. That's how great this is.&lt;p&gt;
&lt;p&gt;&lt;tt&gt;M-x magit-status&lt;/tt&gt; (which I've bound to &lt;tt&gt;C-c i&lt;/tt&gt;) tells you about your working tree and the index, kind of like a combination of &lt;tt&gt;git diff&lt;/tt&gt;, &lt;tt&gt;git diff --cached&lt;/tt&gt;, and &lt;tt&gt;git status&lt;/tt&gt;. It shows some number of sections (e.g. Staged changes, Unstaged changes, etc.); within each section you can see what files have been modified; within each file you can view the individual hunks. Within any of these containers you can press &lt;tt&gt;TAB&lt;/tt&gt; to expand or collapse the heading. Moving your cursor into a file header or a diff hunk header selects the changes in that file or hunk, respectively. You can then press &lt;tt&gt;s&lt;/tt&gt; to stage those changes, as shown in these before-and-after pictures:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/_egN-3IJO0Xg/SVWuB-IPxqI/AAAAAAAAA7o/W5ZqSxsw0ok/s1600-h/magit1.png"&gt;&lt;img src="http://lh4.ggpht.com/_egN-3IJO0Xg/SVWuB-IPxqI/AAAAAAAAA7o/W5ZqSxsw0ok/magit1.png" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Once you're satisfied with your staged changes, you can press &lt;tt&gt;c&lt;/tt&gt; to commit, which prompts you for a log message. After you've typed a message, &lt;tt&gt;C-c C-c&lt;/tt&gt; performs the actual commit.&lt;/p&gt;
&lt;p&gt;This is already much faster than using &lt;tt&gt;git add --interactive&lt;/tt&gt; or &lt;tt&gt;git add --patch&lt;/tt&gt; to stage parts of a file. You just find the hunk you want rather than having git ask you yes/no about every hunk.&lt;/p&gt;
&lt;p&gt;However, Magit also allows staging changes at an even finer granularity. If you highlight some lines in a hunk and then press &lt;tt&gt;s&lt;/tt&gt;, Magit only stages the selected lines, as shown in these before-and-after pictures:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/_egN-3IJO0Xg/SVWvMFUq1RI/AAAAAAAAA7w/VJi3hLB0HrE/s1600-h/magit2.png"&gt;&lt;img src="http://lh4.ggpht.com/_egN-3IJO0Xg/SVWvMFUq1RI/AAAAAAAAA7w/VJi3hLB0HrE/magit2.png" border="0"/&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;When in doubt, it's a good idea to make small commits rather than large commits. It's easy to revert (cherry-pick, explain, etc.) more than one commit, but hard to revert &lt;em&gt;half a commit&lt;/em&gt;. Kudos to Magit for making small commits easier to create.&lt;/p&gt;
&lt;p&gt;Finally, Magit comes with a fine &lt;a href="http://zagadka.vm.bytemark.co.uk/magit/magit.html"&gt;manual&lt;/a&gt;, which you can read online.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Installing Magit&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;It doesn't get too much easier than this for external Emacs packages.&lt;/p&gt;
&lt;p&gt;Check out Magit:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;git clone git://gitorious.org/magit/mainline.git&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Make sure that magit.el from that checkout, or a copy, is on your load path. For example:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;(add-to-list 'load-path (expand-file-name "~/.emacs.d/lisp"))&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Autoload Magit and bind &lt;tt&gt;magit-status&lt;/tt&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;(autoload 'magit-status "magit" nil t)&lt;br&gt;
(global-set-key "\C-ci" 'magit-status)&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-8874621181071085708?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/8874621181071085708/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/12/magit.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8874621181071085708'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8874621181071085708'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/12/magit.html' title='Magit'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh4.ggpht.com/_egN-3IJO0Xg/SVWuB-IPxqI/AAAAAAAAA7o/W5ZqSxsw0ok/s72-c/magit1.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-664718025908462074</id><published>2008-12-22T19:35:00.002-08:00</published><updated>2010-09-29T22:09:07.236-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Ubuntu Jaunty Jackalope</title><content type='html'>&lt;p&gt;(I am catching up on all the things that I've been meaning to blog about in the past few months.)&lt;/p&gt;
&lt;p&gt;There are good reasons already to upgrade to the Jaunty Jackalope (development release). Either for good, or just to install the following two packages:&lt;/p&gt;
&lt;p&gt;(1) git 1.6.x (&lt;a href="http://lkml.org/lkml/2008/8/17/174"&gt;release announcement&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;(2) Firefox 3.1 beta. I have to say, I wasn't sold on Firefox 3.0. But Firefox 3.1 has convinced me to switch back from Epiphany. First, it is blazing fast. Second, in continual usage for several weeks now, it seems to be pretty crash-proof. Third, it actually has a bookmarks system that I would use. When Google can get you what you want 0.5 seconds after you type it in, you really have to rethink the idea of poking around through menus to find your favorite sites. Anyway, my gratitude goes to everyone involved.&lt;/p&gt;
&lt;p&gt;Epiphany had also been starting to get on my nerves lately. It seems to crash at least once every other day. The address bar is really laggy sometimes (if you've ever used SSH over a high-latency connection, you know how irritating this is). And it is not as fast as Firefox 3.1, at least yet.&lt;/p&gt;
&lt;p&gt;Jaunty is interesting for another reason. In this release, Ubuntu is attempting to make &lt;tt&gt;bzr&lt;/tt&gt; repositories &lt;a href="http://package-import.ubuntu.com/"&gt;available&lt;/a&gt; for the packaging+source of every single package. I am looking forward to seeing what people will do with this. If it could make it easier for casual developers to get the source for a package, poke around to fix a bug, isolate their patches and send them to Ubuntu (or upstream), it could be a huge force multiplier.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-664718025908462074?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/664718025908462074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/12/ubuntu-jaunty-jackalope.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/664718025908462074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/664718025908462074'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/12/ubuntu-jaunty-jackalope.html' title='Ubuntu Jaunty Jackalope'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4336286423332704686</id><published>2008-12-20T20:39:00.002-08:00</published><updated>2008-12-20T21:26:46.332-08:00</updated><title type='text'>The Slashdot Top 40</title><content type='html'>&lt;p&gt;For our &lt;a href="http://courses.csail.mit.edu/6.867/"&gt;machine learning&lt;/a&gt; project, we attempted to automatically guess ratings or labels for Slashdot comments based on their content. As a side effect, we generated some data on what words and phrases tend to appear disproportionately often in high-ranked (low-ranked, interesting, uninteresting, funny, unfunny, etc.) comments.&lt;/p&gt;
&lt;p&gt;The set of the top 40 "Funny" phrases turns out to be a hodgepodge of cultural references. I am not sure I understand all of them.&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;1 xkcd.com $
2 xkcd.com
3 nukem forever
4 carrier $
5 slashdot editor
6 skynet
7 clod $
8 woman $
9 grue
10 newt
11 no carrier
12 asparagus
13 nigerian prince
14 porn with
15 grue $
16 an outrage
17 kentucky $
18 eight camera
19 reality distortion
20 god what
21 six video
22 electronic games
23 locally $
24 paperbacks
25 distortion field
26 its belly
27 my underwear
28 am intrigued
29 penny-arcade.com $
30 priceless $
31 lycra
32 emacs $
33 polar bear
34 cried out
35 burma shave
36 an african
37 porn for
38 your grip
39 expects the
40 not talk&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;("$" means end of comment; "^" means beginning of comment.)&lt;/p&gt;
&lt;p&gt;The list of top "Interesting" phrases suggests that workplace stories are interesting:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;employees were; what worked; department i; our clients; wap; reviews on; file servers; work etc; could connect; stance that; updates the; those available; hitting my; europe to; i'm seeing; happening with; snuff; time anyone; spam has; to snuff; the bases; thin and; my college; street to; extreme programming; be neutral; late 19th; management they; from game; tenacity; withstanding; own account; right beside; magpies; from intel's; my food; obscure stuff; language when; and trash; been dragging&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Meanwhile, the phrases least likely to be found in "Interesting" comments are either insulting or profane:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;^ no; insensitive; again $; you insensitive; ^ oh; clod; insensitive clod; ^ you; ^ just; ^ then; ^ well; the hell; ^ or; slashdot; ^ and; you $; post $; ^ yes; ^ why; ^ but; ^ yeah; um; you mean; ^ they; wikipedia.org $; then $; religious; ^ now; clod $; mod; is called; ^ not; right $; ^ he; ^ ah; first post; ^ is; ^ your; ^ it's; fuck&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;These lists were generated using a corpus of 55,561 comments posted between June and November 2008.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4336286423332704686?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4336286423332704686/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/12/slashdot-top-40.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4336286423332704686'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4336286423332704686'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/12/slashdot-top-40.html' title='The Slashdot Top 40'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-8818678985951355629</id><published>2008-11-26T18:30:00.003-08:00</published><updated>2009-01-05T08:23:37.930-08:00</updated><title type='text'>Reading the environment variables of another process</title><content type='html'>&lt;p&gt;If you need to read the environment variables of an arbitrary process, the &lt;tt&gt;/proc&lt;/tt&gt; filesystem makes this easy on Linux. The environment variables are shown in &lt;tt&gt;/proc/&lt;em&gt;PID&lt;/em&gt;/environ&lt;/tt&gt;:&lt;/p&gt;
&lt;pre&gt;$ cat /proc/19065/environ
DISPLAY=localhost:0.0SHELL=/bin/bashPWD=/home/phil...&lt;/pre&gt;
&lt;p&gt;In a shell, it will just look like the variables are smooshed together. They're actually separated by &lt;tt&gt;\0&lt;/tt&gt; (null character), which you can see if you're manipulating this data in some programming language or using a proper text editor:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;C-u M-! cat /proc/19065/environ RET&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;pre&gt;DISPLAY=localhost:0.0&lt;span style="color: red"&gt;^@&lt;/span&gt;SHELL=/bin/bash&lt;span style="color: red"&gt;^@&lt;/span&gt;PWD=/home/phil...&lt;/pre&gt;
&lt;p&gt;[&lt;b&gt;Update&lt;/b&gt;: &lt;tt&gt;ps&lt;/tt&gt; can also be made to show the environment in a manner which is more human-readable but slightly less machine-readable; see comments.]&lt;/p&gt;
&lt;p&gt;(Found via &lt;a href="http://stackoverflow.com/questions/205064/is-there-a-way-to-change-another-processs-environment-variables"&gt;a Stack Overflow post&lt;/a&gt; about &lt;em&gt;changing&lt;/em&gt; another process's environment, which is much more difficult.)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-8818678985951355629?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/8818678985951355629/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/11/reading-environment-variables-of.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8818678985951355629'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8818678985951355629'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/11/reading-environment-variables-of.html' title='Reading the environment variables of another process'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6122185153296002644</id><published>2008-10-26T14:33:00.001-07:00</published><updated>2010-09-29T22:09:07.237-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Stupid screen tricks</title><content type='html'>&lt;p&gt;I use GNU Screen extensively to manage my work. Here are a few Screen tips and shortcuts I've collected or developed.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;1. Add a status bar to screen.&lt;/b&gt; If you use screen inside screen, or screen on more than one machine, having a status bar is essential so you always know where you are. I have the following line in my &lt;tt&gt;.screenrc&lt;/tt&gt;:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;caption always "%{= kw}%-w%{= BW}%n %t%{-}%+w %-= @%H - %LD %d %LM - %c"&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Now whenever I'm within screen, the bottom line looks like this, showing the names of all windows (and highlighting the active one), the hostname, and the date and time:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;pre style="font-size: xx-small; background-color: #000; color: #fff"&gt;&lt;span style="background-color: #008"&gt;0 emacs&lt;/span&gt;  1 bash  2 farm5        @ulysses - Sunday 26 October - 16:06&lt;/pre&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;b&gt;2. Change the screen command key.&lt;/b&gt; For Emacs users, the default screen command key, &lt;tt&gt;C-a&lt;/tt&gt;, is unacceptable. The following line in &lt;tt&gt;.screenrc&lt;/tt&gt; changes it to &lt;tt&gt;C-o&lt;/tt&gt;, which is still bound in Emacs, but less objectionable:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;escape ^Oo&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;b&gt;3. Shortcut resuming screen.&lt;/b&gt; Whenever I SSH to my desktop machine the first thing I do&amp;mdash; always&amp;mdash; is resume my previous screen session. The following command runs &lt;tt&gt;ssh&lt;/tt&gt; and resumes screen in one fell swoop:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;ssh -t ulysses "screen -d -r"&lt;/code&gt;&lt;p&gt;&lt;/blockquote&gt;
&lt;p&gt;I stick that in a script called &lt;tt&gt;homebase&lt;/tt&gt; and bind a hotkey, &lt;tt&gt;[Windows]-h&lt;/tt&gt;, to&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;gnome-terminal -e ~/scripts/homebase&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;in Openbox so I'm only ever one key away.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;4. Use nested screens.&lt;/b&gt; My desktop machine has good connectivity, so from my screen there, I connect to a bunch of remote machines which I use for my work, and of course, I use screen on those hosts too.&lt;/p&gt;
&lt;p&gt;To send a &lt;tt&gt;C-o&lt;/tt&gt; to a screen instance which is itself inside a screen window, you need to escape it and type &lt;tt&gt;C-o o&lt;/tt&gt;. So, for example, if &lt;tt&gt;C-o n&lt;/tt&gt; is usually used to go to the next window, you'll need to use &lt;tt&gt;C-o o n&lt;/tt&gt; to go to the next window in a nested instance. This setup is hard to beat for managing connections to multiple computers. It sounds complicated, but your muscle memory will take care of it soon.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;5. Generate new windows automatically.&lt;/b&gt; Whenever I SSH into another host from inside screen, I usually want a dedicated window for that connection. The following snippet in my &lt;tt&gt;.bashrc&lt;/tt&gt; makes it so that when I'm inside screen and type &lt;tt&gt;ssh SOME-HOST&lt;/tt&gt;, it creates a new window and titles it &lt;tt&gt;SOME-HOST&lt;/tt&gt;, then invokes &lt;tt&gt;ssh&lt;/tt&gt; in the new window.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;pre&gt;# Opens SSH on a new screen window with the appropriate name.
screen_ssh() {
    numargs=$#
    screen -t ${!numargs} ssh $@
}
if [ $TERM == "screen" -o $TERM == "screen.linux" ]; then
    alias ssh=screen_ssh
fi&lt;/pre&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;(Caveat: this doesn't quite work when you specify a host and a command on the same line, e.g. &lt;tt&gt;ssh some-host "ls ~"&lt;/tt&gt;.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;6. Managing DISPLAYs.&lt;/b&gt; The disconnect-and-resume-anytime way of working can sometimes be a curse. Shells inside screen windows don't get environment variables like &lt;tt&gt;$DISPLAY&lt;/tt&gt; updated whenever you resume a session. So if you carelessly launch an X program from inside one, it may end up on a display which is either long gone or not the one you intended to use. The following simple trick automagically sets DISPLAY to the display at the last place you resumed a screen session (i.e. probably where you are sitting right now).&lt;/p&gt;
&lt;p&gt;First, write the value of &lt;tt&gt;$DISPLAY&lt;/tt&gt; to a file whenever you resume screen. One way to do this is by using a shell alias like the following whenever you resume, instead of using &lt;tt&gt;screen -d -r&lt;/tt&gt; directly:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;alias sc='echo $DISPLAY&gt;~/.last-display; screen -d -r'&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Alternatively, the invocation from #3, above, might now look like this:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;ssh -X -t ulysses "echo \$DISPLAY&gt;~/.last-display; screen -d -r"&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Now, this shell alias &lt;tt&gt;here&lt;/tt&gt; sets the display appropriately, so that, for example, &lt;tt&gt;here xterm&lt;/tt&gt; runs &lt;tt&gt;xterm&lt;/tt&gt; on your "current" display:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;alias here='DISPLAY=`cat ~/.last-display`'&lt;/code&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6122185153296002644?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6122185153296002644/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/10/stupid-screen-tricks.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6122185153296002644'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6122185153296002644'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/10/stupid-screen-tricks.html' title='Stupid screen tricks'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-9107740968537769200</id><published>2008-10-07T07:40:00.003-07:00</published><updated>2008-10-07T08:39:12.800-07:00</updated><title type='text'>Booting Linux in five seconds</title><content type='html'>&lt;p&gt;This has been floating around for a couple of weeks now, but it is a good read.&lt;/p&gt;
&lt;p&gt;At the Linux Plumbers Conference a few weeks back, two Linux developers employed by Intel demonstrated an Eee PC with GNU/Linux which had been modified to boot, to a full graphical environment, in five seconds:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;They had to hold up the EEE PC for the audience, since the time required to finish booting was less than the time needed for the projector to sync.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;a href="http://lwn.net/Articles/299483/"&gt;LWN writeup&lt;/a&gt; contains many details of their talk and includes quite a few interesting tidbits. (X runs a C preprocessor and compiler every time it boots? Seriously?) The two engineers conclude that the culprit for poor boot time is scores of components providing power and flexibility which only a few people use but everyone has to pay for, like the following:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;[Ubuntu] spends 12 seconds running modprobe running a shell running modprobe, which ends up loading a single module. The tool for adding license-restricted drivers takes 2.5 seconds&amp;mdash; on a system with no restricted drivers needed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is also a good example of the kind of innovation that simply cannot happen on proprietary systems. Information about the entire Linux/GNU/services/X stack is freely available and modifiable, and one consequence of this is that it is very easy to build on the progress of others. It then becomes strikingly clear that all of us is smarter than any one of us, and substantially more creative.&lt;/p&gt;
&lt;p&gt;Moreover, the experience obtained here is actually being used to help improve future versions of our operating systems, rather than being confined to the backwater of hacks that appear on Slashdot and are never heard from again.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-9107740968537769200?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/9107740968537769200/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/10/booting-linux-in-five-seconds.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/9107740968537769200'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/9107740968537769200'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/10/booting-linux-in-five-seconds.html' title='Booting Linux in five seconds'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4127729239413801230</id><published>2008-09-30T21:30:00.002-07:00</published><updated>2008-09-30T22:29:37.158-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='maxwell'/><title type='text'>Maxwell now renders output nicely-er</title><content type='html'>&lt;p&gt;&lt;img src="http://web.psung.name/maxwell/screenshots/text.png" style="padding: 3px; border: 1px solid #999"&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://web.psung.name/maxwell/"&gt;Maxwell&lt;/a&gt; now prints the circuit element values next to each element. I suppose this makes it somewhat more useful for demonstration purposes.&lt;/p&gt;
&lt;p&gt;This is done using the &lt;a href="http://www.whatwg.org/specs/web-apps/current-work/#text"&gt;WHATWG Canvas text API&lt;/a&gt;, which is newly supported in Firefox 3.1, thanks to &lt;a href="http://www.ericbutler.net/blog/"&gt;Eric Butler&lt;/a&gt;. (Firefox 3.0 users will get the old behavior, where the element values are printed in the status area upon mouseover.)&lt;/p&gt;
&lt;p&gt;Ubuntu Intrepid (8.10) users can get Firefox 3.1 alpha packages from &lt;a href="https://launchpad.net/~fta/+archive"&gt;Fabien Tassin's PPA&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4127729239413801230?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4127729239413801230/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/10/maxwell-now-renders-output-nicely-er.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4127729239413801230'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4127729239413801230'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/10/maxwell-now-renders-output-nicely-er.html' title='Maxwell now renders output nicely-er'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-1002754132706463034</id><published>2008-09-26T17:41:00.009-07:00</published><updated>2010-04-20T20:39:35.241-07:00</updated><title type='text'>Scrolling with the Thinkpad's TrackPoint in Ubuntu</title><content type='html'>&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; for instructions for &lt;b&gt;Ubuntu Lucid/10.04&lt;/b&gt; see &lt;a href="http://psung.blogspot.com/2010/04/thinkpad-trackpoint-scrolling-in-ubuntu.html"&gt;this post&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; note, these instructions work for me on Ubuntu 8.10 Intrepid as well as 9.04 Jaunty and 9.10 Karmic on a Thinkpad X61s. Alternatively, the Karmic repos have &lt;tt&gt;&lt;a href="http://live.gnome.org/GPointingDeviceSettings"&gt;gpointing-device-settings&lt;/a&gt;&lt;/tt&gt;, a GUI tool for enabling trackpoint scrolling (as well as other special trackpoint/touchpad features).&lt;/p&gt;
&lt;p&gt;Ubuntu GNU/Linux 8.10 (Intrepid) switches to &lt;tt&gt;evdev&lt;/tt&gt; for X server input, which has the unfortunate side effect of breaking old &lt;tt&gt;EmulateWheel&lt;/tt&gt; configurations. So scrolling using the middle button + TrackPoint (&lt;a href="http://philipsung.blogspot.com/2008/03/thinkpad-x61s-and-lenovo-scrollpoint.html"&gt;which I absolutely love&lt;/a&gt;) was broken for a while, although it is now fixed. Instead of modifying your &lt;tt&gt;xorg.conf&lt;/tt&gt;, create a new file called &lt;tt&gt;/etc/hal/fdi/policy/mouse-wheel.fdi&lt;/tt&gt; with the following contents:&lt;/p&gt;
&lt;p&gt;&lt;pre&gt;&amp;lt;match key="info.product" string="TPPS/2 IBM TrackPoint"&amp;gt;
 &amp;lt;merge key="input.x11_options.EmulateWheel" type="string"&amp;gt;true&amp;lt;/merge&amp;gt;
 &amp;lt;merge key="input.x11_options.EmulateWheelButton" type="string"&amp;gt;2&amp;lt;/merge&amp;gt;
 &amp;lt;merge key="input.x11_options.XAxisMapping" type="string"&amp;gt;6 7&amp;lt;/merge&amp;gt;
 &amp;lt;merge key="input.x11_options.YAxisMapping" type="string"&amp;gt;4 5&amp;lt;/merge&amp;gt;
 &amp;lt;merge key="input.x11_options.ZAxisMapping" type="string"&amp;gt;4 5&amp;lt;/merge&amp;gt;
 &amp;lt;merge key="input.x11_options.Emulate3Buttons" type="string"&amp;gt;true&amp;lt;/merge&amp;gt;
&amp;lt;/match&amp;gt;&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;(Based on code from &lt;a href="http://mvogt.wordpress.com/2008/08/15/xorg-evdev-and-emulatewheel/"&gt;Michael Vogt&lt;/a&gt; and adapted to support both vertical and horizontal scrolling.)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; you'll have to restart &lt;tt&gt;hal&lt;/tt&gt; and &lt;tt&gt;gdm&lt;/tt&gt;, and remove the cache file &lt;tt&gt;/var/cache/hald/fdi-cache&lt;/tt&gt;, for the changes to take effect. &lt;b&gt;Log in on a VT&lt;/b&gt; (e.g. with &lt;tt&gt;Ctrl+Alt+F1&lt;/tt&gt;) and then do:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;sudo rm /var/cache/hald/fdi-cache&lt;br&gt;sudo /etc/init.d/hal restart&lt;br&gt;sudo /etc/init.d/gdm restart&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;(Be sure to &lt;em&gt;log in on a console/VT&lt;/em&gt;, because restarting GDM will kill all your X apps...)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Note for Ubuntu 8.10 users only:&lt;/b&gt; an update to Ubuntu Intrepid (subsequent to my original post) breaks TrackPoint scrolling either completely or possibly only after suspending and resuming. A comment on &lt;a href="https://bugs.launchpad.net/ubuntu/+source/xserver-xorg-input-evdev/+bug/282387/comments/18"&gt;Ubuntu bug 282387&lt;/a&gt; gives instructions for downloading and installing a fixed version from upstream:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;sudo apt-get install build-essential git-core&lt;br&gt;
sudo apt-get build-dep xserver-xorg-input-evdev&lt;br&gt;
git clone git://git.freedesktop.org/git/xorg/driver/xf86-input-evdev&lt;br&gt;
cd xf86-input-evdev&lt;br&gt;
git reset --hard 5f2c8a2dcdf98b39997ee5e7c9a9ace3b640bfa3&lt;br&gt;
./autogen.sh --prefix=/usr&lt;br&gt;
make&lt;br&gt;
sudo make install&lt;br&gt;&lt;/tt&gt;&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Later releases already have a fixed version of xserver-xorg-input-evdev.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Feedback/testing:&lt;/b&gt; I've tested the policy file and workaround above on an X61s. On 8.04/Intrepid, people have indicated that it seems to work on most or all R and T series Thinkpads as well as the X31, X40, X61, and X200. The X300 and X301 Thinkpads seem to have different TrackPoint hardware. On those machines you may need to disable the touchpad in the BIOS to make the above workaround work.&lt;/p&gt;
&lt;p&gt;Thanks to all the commenters below who left additional tips for getting this to work and providing feedback on what hardware is supported!&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-1002754132706463034?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/1002754132706463034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/09/scrolling-with-thinkpads-trackpoint-in.html#comment-form' title='101 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1002754132706463034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1002754132706463034'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/09/scrolling-with-thinkpads-trackpoint-in.html' title='Scrolling with the Thinkpad&apos;s TrackPoint in Ubuntu'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>101</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4530626874261491540</id><published>2008-09-22T22:20:00.003-07:00</published><updated>2008-09-22T22:45:30.750-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='freerunner'/><title type='text'>Fixing low call volume on the Freerunner</title><content type='html'>&lt;p&gt;Here's a workaround for fixing the one sound issue I've had with the Freerunner, namely that the people I'm calling complain that I'm too quiet. This is caused by a mixer setting which makes the mic volume on the Freerunner too low. My gratitude to the folks on the OM mailing lists who managed to piece this (very easy) solution together.&lt;/p&gt;
&lt;p&gt;This kind of problem can be corrected just by running &lt;tt&gt;alsamixer&lt;/tt&gt; while a call is in progress. Play around with the volume on the various channels until you are satisfied. In particular, raising the "Sidetone" volume seems to do the trick. This will fix the problem, at least for that call.&lt;/p&gt;
&lt;p&gt;ASU keeps different sets of mixer settings for all sorts of scenarios (e.g. headset, handset, speakerphone, etc.). However, every time one of these scenarios is activated, ASU just loads the mixer settings from a file. If you change the settings in &lt;tt&gt;alsamixer&lt;/tt&gt;, those changes never get written back to the file, so they aren't applied in the future.&lt;/p&gt;
&lt;p&gt;To save those changes, adjust the settings to your satisfaction and then, during the call, to save your new mixer settings, do this:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;alsactl -f /home/root/newsettings.state store&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Use that to overwrite the file from which the mixer settings are read, which is &lt;tt&gt;/usr/share/openmoko/scenarios/gsmhandset.state&lt;/tt&gt; (if you are curious, you can also play around with the other &lt;tt&gt;.state&lt;/tt&gt; files in that directory).&lt;/p&gt;
&lt;p&gt;For me, the net result of all this was the same as applying the following one-line patch to &lt;tt&gt;/usr/share/openmoko/scenarios/gsmhandset.state&lt;/tt&gt;. You can try it too, if you dare:&lt;/p&gt;
&lt;pre&gt;--- old/gsmhandset.state Tue Sep 23 01:20:14 2008
+++ new/gsmhandset.state Mon Sep 22 00:16:28 2008
@@ -112,7 +112,7 @@
   comment.range '0 - 7'
   iface MIXER
   name 'Mono Sidetone Playback Volume'
-  value 2
+  value 6
  }
  control.13 {
   comment.access 'read write'&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4530626874261491540?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4530626874261491540/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/09/fixing-low-call-volume-on-freerunner.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4530626874261491540'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4530626874261491540'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/09/fixing-low-call-volume-on-freerunner.html' title='Fixing low call volume on the Freerunner'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-1868984359952524162</id><published>2008-09-22T21:17:00.004-07:00</published><updated>2008-09-22T22:20:14.521-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='freerunner'/><title type='text'>OM 2008.8 and 2008.9 impressions</title><content type='html'>&lt;p&gt;Development is continuing at an incredible pace on the OpenMoko software. OM 2008.8 (the "ASU") was released in August and I installed it when I got back from my vacation. I also tried OM 2008.9 when was released last week. It looks like they are going to continue with updates monthly like this. This software is still rough around the edges but at this point the Freerunner is definitely usable as a primary phone now (while, I would argue, it was not with 2007.2).&lt;/p&gt;
&lt;p&gt;To be honest, both of the 2008 series updates are very much "fix two bugs, introduce one bug". Nevertheless, the software is improving by leaps and bounds. The ASU software is a big improvement over the original GTK stack. Notably, it is much more finger-friendly, not requiring a stylus (or fingernails) for as many tasks.&lt;/p&gt;
&lt;p&gt;Here are some of the most visible bugs that were fixed (hooray!):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2007.2's sound broke after resuming from suspend. This meant that if you wanted to use your phone, you could not really suspend it. This was fixed in 2008.8.&lt;/li&gt;
&lt;li&gt;Call connectivity was somewhat inconsistent in 2008.8. People reported that when they called me, the call would go directly to voicemail. I occasionally had to redial a number because the first call would just die. These &lt;em&gt;appear&lt;/em&gt; to have gone away in 2008.9.&lt;/li&gt;
&lt;li&gt;Time zones did not persist after rebooting in 2008.8. This has been fixed in 2008.9.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To put the situation in perspective, here are, in my view, the most visible/annoying bugs that remain. None of these really block normal phone use.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I don't think connecting to the internet via wifi works, although in 2008.9 it actually detects APs now.&lt;/li&gt;
&lt;li&gt;Battery life seems to be worse on 2008.9 than 2008.8.&lt;/li&gt;
&lt;li&gt;Upon being woken from suspend, the phone will go right back to sleep. I have to press the power button twice to wake the phone.&lt;/li&gt;
&lt;li&gt;2008.9 seems to crash and die more often than 2009.8. This seems to be related to suspending or waking the phone.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One other bug I've had is an issue with sound quality (the volume being too low). I'll show you how I'm working around that in my next post.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-1868984359952524162?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/1868984359952524162/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/09/om-20088-and-20089-impressions.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1868984359952524162'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1868984359952524162'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/09/om-20088-and-20089-impressions.html' title='OM 2008.8 and 2008.9 impressions'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4820027409228576965</id><published>2008-09-21T10:35:00.000-07:00</published><updated>2008-09-21T10:35:40.233-07:00</updated><title type='text'>Interesting recent talks</title><content type='html'>&lt;p&gt;Some interesting talks I heard recently:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://people.csail.mit.edu/rivest/"&gt;Ron Rivest&lt;/a&gt; talked about &lt;a href="http://people.csail.mit.edu/rivest/Rivest-TheMD6HashFunction.ppt"&gt;the MD6 hash function&lt;/a&gt;, which is a candidate in the upcoming SHA-3 hash contest, sponsored by NIST. It is based on a tree structure instead of a chain structure so that it's parallelizable, is resistant against certain cut-and-paste attacks, and is &lt;em&gt;provably&lt;/em&gt; resistant to &lt;a href="http://en.wikipedia.org/wiki/Differential_cryptanalysis"&gt;differential attacks&lt;/a&gt;, which have been worrying people. Extensive computer simulations were used to verify that MD6 "scrambles" its inputs enough to put a lower bound on the complexity of this particular kind of attack which is higher than the birthday bound.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.isi.edu/~knight/"&gt;Kevin Knight&lt;/a&gt; gave a talk on machine translation &lt;em&gt;without parallel texts&lt;/em&gt;. Which sounds, on the face of it, absurd. Except that translation can be thought of as just applying a secret code, and statistical methods for cracking codes (without having much/any parallel text, of course!) have been around for a long time. Nowadays, computers can solve the &lt;a href="http://en.wikipedia.org/wiki/Cryptogram"&gt;cryptogram&lt;/a&gt; you find in the newspaper, and some analagous problems, but we don't know a whole lot about stuff beyond that. This kind of research could be useful for helping to translate texts in specific domains (e.g. computer manuals), where lots of example text can be found but little parallel text is available. Methods trained on general corpora often do quite poorly in this kind of niche.&lt;/p&gt;
&lt;p&gt;By the way, I love &lt;a href="http://www.isi.edu/natural-language/people/pictures2/basketball.jpg"&gt;this comic by Kevin Knight&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4820027409228576965?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4820027409228576965/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/09/interesting-recent-talks.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4820027409228576965'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4820027409228576965'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/09/interesting-recent-talks.html' title='Interesting recent talks'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-1144505079303297086</id><published>2008-09-20T18:21:00.012-07:00</published><updated>2008-09-20T23:16:17.914-07:00</updated><title type='text'>Software Freedom Day 2008 Boston; Happy 25th birthday to GNU</title><content type='html'>&lt;p&gt;I went to the Software Freedom Day 2008 event in Boston today. It was a good opportunity to learn about the fascinating things people are doing with free software (and free culture ideas in general), as well as to learn about some of the major threats to our freedom, and some things we can do about them. Thanks to everyone who was involved.&lt;/p&gt;
&lt;p&gt;Some nifty things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://mihmo.livejournal.com/"&gt;M&amp;aacute;ir&amp;iacute;n Duffy&lt;/a&gt; spoke about how she makes, among other things, the Fedora Project's artwork (web graphics, signage, CDs, etc.) using only free software tools. This is a shining example of how users of free software gain autonomy: her clients can fix up or update her work instead of having to ask her to do it. This would be much more difficult if those people, who are not graphics professionals, had to shell out $1100 for Adobe Creative Suite. Open formats are a huge plus, too: being able to programmatically modify images at a high level is a huge time-saver.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://chdk.wikia.com/wiki/CHDK"&gt;CHDK&lt;/a&gt; is free firmware which supplements the firmware in some Canon digital cameras. People are using it to add all kinds of &lt;a href="http://chdk.wikia.com/wiki/CHDK_firmware_usage"&gt;awesome new features&lt;/a&gt; to the camera, such as battery meters (not available on low-end cameras), RAW support, live histograms, focus and exposure bracketing, automatic photography of lightning, and &lt;a href="http://chdk.wikia.com/wiki/CHDK_firmware_usage#Game:_Reversi"&gt;reversi&lt;/a&gt;. And &lt;a href="http://chdk.wikia.com/wiki/Samples:_High-Speed_Shutter_%26_Flash-Sync"&gt;high speed photography&lt;/a&gt; which, seriously, looks like some of those Doc Edgerton strobe photos, except they were taken using a $100 digital camera.&lt;/li&gt;
&lt;li&gt;"What if Wikipedia only allowed you to enter statements that were true?" &lt;a href="http://math.mit.edu/~freer/"&gt;Cameron Freer&lt;/a&gt; is building &lt;a href="http://vdash.org/"&gt;vdash.org&lt;/a&gt;, which will be a wiki of computer-verifiable proofs. Imagine: our kids might learn math out of interactive textbooks where you could click on any step in a proof and ask "Why?" and it would expand to fill in the gaps in the proof. That would almost be straight out of &lt;a href="http://en.wikipedia.org/wiki/The_Diamond_Age"&gt;&lt;em&gt;The Diamond Age&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.aaronsw.com/"&gt;Aaron Swartz&lt;/a&gt; talked about his newest venture, &lt;a href="http://watchdog.net/"&gt;watchdog.net&lt;/a&gt;, "a hub for data about politics". But he also talked more generally about the somewhat unconventional ways in which he is trying to coordinate people to help get public data onto the internet. The idea that there are certain kinds of knowledge that rightfully belong to "us" (the public) and not any one single entity is quite refreshing in this age of government/institutional opacity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now, for the bad news. The two most talked-about threats to free software were mobile phones and DRM. The big two software makers have done a good job of convincing people that they shouldn't care about freedom on phones because it's "just a phone". But if you think of all the things you can do on phones nowadays, you realize that you really don't want to surrender your autonomy there, regardless of what your phone maker claims. DRM is a little better. It has been somewhat widely discredited in a number of high-profile incidents now. Sadly, that doesn't keep people from trying it.&lt;/p&gt;
&lt;p&gt;Advocating free software should be easy, right? (Ed.: apparently, no.) After all, the big proprietary software companies have made huge missteps lately. They just can't stop making their software more and more restrictive and obnoxious! Not to take pride in the misfortune of their customers, but I believe there is a good chance that in the short term future it will become increasingly clear to many "ordinary folks" that proprietary software is not just a theoretical hazard but a real liability. Multiply that danger by the pervasiveness of software in our everyday lives and business, an extent which probably even most technically-minded people fail to completely appreciate. So I believe that projects like Mako Hill's &lt;a href="http://revealingerrors.com/"&gt;Revealing Errors&lt;/a&gt; are a critical link in helping people, especially non-technical people, understand the importance of free software.&lt;/p&gt;
&lt;p&gt;Happy 25th birthday to GNU! Richard Stallman gave a lightning talk about the story of GNU, among other things. To hear it from the horse's mouth on this anniversary helped to put in perspective how far we have come in the last 25 years, and how far we still have to go. (Boy, do I feel odd personally identifying with a movement that is older than I am.) May the next 25 years be just as productive.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-1144505079303297086?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/1144505079303297086/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/09/software-freedom-day-2008-boston-happy.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1144505079303297086'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1144505079303297086'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/09/software-freedom-day-2008-boston-happy.html' title='Software Freedom Day 2008 Boston; Happy 25th birthday to GNU'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-248677072581974049</id><published>2008-09-18T20:48:00.000-07:00</published><updated>2010-09-29T22:09:07.237-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Emacs 22.3 released; emacs-snapshot packages for Ubuntu</title><content type='html'>&lt;p&gt;Emacs 22.3 was released on 5 September 2008.&lt;/p&gt;
&lt;p&gt;You may know that Romain Francoise maintains a repository with &lt;a href="http://emacs.orebokech.com"&gt;emacs-snapshot packages for Debian&lt;/a&gt; updated weekly. Well, what about Ubuntu users? Since earlier this summer-ish, the &lt;a href="https://launchpad.net/~ubuntu-elisp/+archive"&gt;ubuntu-elisp PPA&lt;/a&gt; has also been receiving emacs-snapshot packages regularly! Great news for those of us who always want to try out the features that the awesome hackers on &lt;tt&gt;emacs-devel&lt;/tt&gt; are writing about.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-248677072581974049?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/248677072581974049/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/09/emacs-223-released-emacs-snapshot.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/248677072581974049'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/248677072581974049'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/09/emacs-223-released-emacs-snapshot.html' title='Emacs 22.3 released; emacs-snapshot packages for Ubuntu'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-1385955659097041450</id><published>2008-09-18T18:26:00.002-07:00</published><updated>2010-09-29T22:09:07.238-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Report: Ubuntu Intrepid on the OLPC XO-1</title><content type='html'>&lt;p&gt;I have a setup that I'm quite pleased with on my Ubuntu machines, so I recently installed Ubuntu to my XO-1, thinking that I would get more out of the machine than I have with Sugar/Fedora. I bought a 4GB SD card to use with the machine and followed &lt;a href="http://wiki.laptop.org/go/Ubuntu_On_OLPC_XO"&gt;these instructions&lt;/a&gt;, which call for installing to a disk image within Qemu and then copying that disk image to an SD card.&lt;/p&gt;
&lt;p&gt;I installed an alpha of Ubuntu Intrepid Ibex 8.10 without any major hitches. It works. I'm using Openbox as my window manager, which keeps touchpad use to a minimum.&lt;/p&gt;
&lt;p&gt;Some remarks on what hardware works out of the box, with Ubuntu Intrepid:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Wireless works.&lt;/li&gt;
&lt;li&gt;Display works. According to &lt;tt&gt;glxinfo&lt;/tt&gt; it is doing direct rendering. &lt;tt&gt;glxgears&lt;/tt&gt; runs at a whopping &lt;em&gt;22&lt;/em&gt; frames per second.&lt;/li&gt;
&lt;li&gt;The brightness and volume keys don't work out of the box. The volume keys ("F11" and "F12", really) can be configured through GNOME. I do not know whether there is a quick way to get GNOME to also recognize the brightness keys ("F9" and "F10", really).&lt;/li&gt;
&lt;li&gt;X recognizes the game keys but not the rocker.&lt;/li&gt;
&lt;li&gt;The touchpad works, but is hyper-sensitive and registers taps all the time when you are using it. To disable tap-to-click, add a line reading &lt;tt&gt;options mousedev tap_time=0&lt;/tt&gt; to your &lt;tt&gt;/etc/modprobe.d/olpc.conf.dist&lt;/tt&gt;. (&lt;a href="http://jeremy.visser.name/2008/05/02/ubuntu-on-the-olpc-xo-1/"&gt;Source&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;The microphone light is on all the time. I wonder if this is causing some power drain I don't want (apart from the light itself).&lt;/li&gt;
&lt;li&gt;Cheese does not recognize the webcam.&lt;/li&gt;
&lt;li&gt;Ubuntu does not know how to suspend-to-RAM the machine. It claims to be able to hibernate, but I haven't actually tried it.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It's a little poky, but more than adequate for using Emacs, reading mail, and browsing the web.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-1385955659097041450?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/1385955659097041450/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/09/report-ubuntu-intrepid-on-olpc-xo-1.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1385955659097041450'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/1385955659097041450'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/09/report-ubuntu-intrepid-on-olpc-xo-1.html' title='Report: Ubuntu Intrepid on the OLPC XO-1'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-4181127496108438887</id><published>2008-09-13T13:57:00.002-07:00</published><updated>2008-09-17T18:02:40.888-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Reading your mail in Emacs with VM</title><content type='html'>&lt;p&gt;I posted an article on &lt;a href="http://web.psung.name/emacstips/vm.html"&gt;reading your mail with VM&lt;/a&gt; in Emacs, which contains a minimal VM orientation, information about how I read mail in VM, and the elisp configuration I used to set that up.&lt;/p&gt;
&lt;p&gt;I attempted the switch a couple of months back after realizing that the volume of email I was dealing with was seriously impairing my work ability. Gmail does have some tools for managing lots of email (labels), but with VM I can be much more fine-grained about what messages I look at at any particular time. Scanning and reading mail is also much faster, if only because I don't have to wait for the RTT to a Google server and the browser render time every time I want to do something.&lt;/p&gt;
&lt;p&gt;And, of course, the best part of VM is that it comes with a great e-mail editor.&lt;/p&gt;
&lt;p&gt;Why VM? The big choices are Gnus, VM, and MH-E. I had tried Gnus and couldn't really wrap my head around its model of doing things. MH-E sounded acceptable but I assumed that VM, which had more Lisp implementation, would probably be more flexible. I am pretty happy with VM, but I suspect that changing mail clients is really just a matter of performing a conversion process on the mail folder files. Some operations (such as writing an entire mailbox to disk) are probably slower than they could be, but in general it is blazing fast.&lt;/p&gt;
&lt;p&gt;I also wrote about setting up BBDB (the Insidious Big Brother Database), an address book program which is strangely satisfying to use.&lt;/p&gt;
&lt;p&gt;Read about &lt;a href="http://web.psung.name/emacstips/vm.html"&gt;my VM configuration and workflow&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-4181127496108438887?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/4181127496108438887/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/09/reading-your-mail-in-emacs-with-vm.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4181127496108438887'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/4181127496108438887'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/09/reading-your-mail-in-emacs-with-vm.html' title='Reading your mail in Emacs with VM'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-2423923113507433333</id><published>2008-09-11T19:25:00.002-07:00</published><updated>2008-09-11T19:57:41.574-07:00</updated><title type='text'>Who thought of this stuff?</title><content type='html'>&lt;p&gt;Matlab's documentation for the &lt;tt&gt;logspace&lt;/tt&gt; function:&lt;/p&gt;
&lt;pre&gt;&amp;gt;&amp;gt; help logspace
 LOGSPACE Logarithmically spaced vector.
    LOGSPACE(X1, X2) generates a row vector of 50 logarithmically
    equally spaced points between decades 10^X1 and 10^X2.  If X2
    is pi, then the points are between 10^X1 and pi [instead].&lt;/pre&gt;
&lt;p&gt;This very odd specification is, of course, totally well-intentioned. The &lt;a href="http://www.mathworks.com/access/helpdesk/help/techdoc/index.html?/access/helpdesk/help/techdoc/ref/logspace.html"&gt;online documentation&lt;/a&gt; gives this rationale:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;tt&gt;y = logspace(a,pi)&lt;/tt&gt; generates the points between &lt;tt&gt;10^a&lt;/tt&gt; and &lt;tt&gt;pi&lt;/tt&gt;, which is useful for digital signal processing where frequencies over this interval go around the unit circle.&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;Unfortunately, half the Matlab functions I read about seem to have these bizarre corner cases and caveats. I can't help but think that this is the numerical equivalent of Perl and the "penny wise, pound foolish" approach to language design: all these odd shortcuts make Matlab code (slightly) easier to write but harder to debug, read, and learn from.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-2423923113507433333?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/2423923113507433333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/09/who-thought-of-this-stuff.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2423923113507433333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/2423923113507433333'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/09/who-thought-of-this-stuff.html' title='Who thought of this stuff?'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-3205924184779297156</id><published>2008-09-04T19:15:00.006-07:00</published><updated>2008-09-05T07:37:34.425-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='emacs'/><title type='text'>Coloring email in Emacs VM</title><content type='html'>&lt;p&gt;I do like Gmail, but (1) it feels sluggish, (2) writing anything nontrivial in a browser text box is just too awkward, and (3) I occasionally wish I had a copy of my mail accessible offline. So I've been trying to switch over to retrieving and reading my mail in Emacs. After a failed experiment in using Gnus to read my mail last year, I recently mustered the energy to try VM.&lt;/p&gt;
&lt;p&gt;It seems to be working well, and I'll write more about my configuration and workflow later, but I wanted to mention one package that I just found.&lt;/p&gt;
&lt;p&gt;One of the (few) things I liked about Gnus was that it color-coded the blurbs in each message by author, which it inferred from the line prefixes ("&amp;gt;", "&amp;gt;&amp;gt;", etc.), like so:&lt;/p&gt;
&lt;a href="http://www.gnu.org/software/emacs/tour/images/gnus.png"&gt;&lt;img src="http://lh6.ggpht.com/philbert/SMCaR3-yiXI/AAAAAAAAArs/apmDdZ-R4xQ/s800/gnus.png" style="border: 1px solid #888"/&gt;&lt;/a&gt;
&lt;p&gt;VM doesn't support such functionality out of the box, but the package &lt;a href="http://de.geocities.com/ulf_jasper/lisp/u-vm-color.el.txt"&gt;u-vm-color.el&lt;/a&gt; mimics it. The package is fairly straightforward to install and works as advertised.&lt;/p&gt;
&lt;p&gt;One thing I discovered that when you run a TTY Emacs it assumes that it is working with light text on a dark background. If you are running Emacs in an xterm with dark text on a light background, you'll need to supply the &lt;tt&gt;-rv&lt;/tt&gt; (reverse video) option to Emacs. Otherwise, Emacs may choose unreadable, or at least, suboptimal, colors for all its faces.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-3205924184779297156?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/3205924184779297156/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/09/coloring-email-in-emacs-vm.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/3205924184779297156'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/3205924184779297156'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/09/coloring-email-in-emacs-vm.html' title='Coloring email in Emacs VM'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh6.ggpht.com/philbert/SMCaR3-yiXI/AAAAAAAAArs/apmDdZ-R4xQ/s72-c/gnus.png' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6151466317010516461</id><published>2008-07-25T09:04:00.002-07:00</published><updated>2008-07-25T09:30:40.463-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='freerunner'/><title type='text'>Sharing GPS tracks from tangoGPS on Google Maps</title><content type='html'>&lt;p&gt;Now that GPS is working on the FreeRunner I made a track log of my commute to test it out. It's pretty easy to get log data off of the FreeRunner and plot it on the web in a Google Map:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First, install &lt;a href="http://www.tangogps.org/gps/cat/News"&gt;tangoGPS&lt;/a&gt;. The latest tangoGPS packages for the FreeRunner, and instructions for installing them, are available &lt;a href="http://www.tangogps.org/gps/cat/Download"&gt;from this page&lt;/a&gt;. It usually takes my FreeRunner a couple of minutes to get its first fix. If you are having problems, &lt;a href="http://wiki.openmoko.org/wiki/Getting_Started_with_your_Neo_FreeRunner#GPS.2C_GPRS_and_WLAN"&gt;OpenMoko's AGPS program&lt;/a&gt; may be able to give some debugging information.&lt;/li&gt;
&lt;li&gt;TangoGPS will appear as an application called "GPS &amp;amp; Map". To record tracks, go to the "Track" tab and click "Start" (and then "Stop", obviously, when you're done).&lt;/li&gt;
&lt;li&gt;TangoGPS will save the track log in &lt;tt&gt;/tmp&lt;/tt&gt; (by default, but it's configurable) in a file with the extension &lt;tt&gt;.log&lt;/tt&gt; and named after the current date/time. When you get back to a computer, &lt;tt&gt;scp&lt;/tt&gt; that file over.&lt;/li&gt;
&lt;li&gt;GPX is a commonly used format for representing GPS track data. You will need to convert your log data to GPX using &lt;a href="http://www.tangogps.org/downloads/convert2gpx.pl"&gt;convert2gpx.pl&lt;/a&gt;, a script provided by TangoGPS. Download it, make it executable, and use it like so: &lt;tt&gt;./convert2gpx.pl&amp;nbsp;inputlogfile.log&amp;nbsp;&amp;gt;&amp;nbsp;outputfile.gpx&lt;/tt&gt;.&lt;/li&gt;
&lt;li&gt;There are some web sites which will let you upload a GPX file and then plot it on a Google Map. &lt;a href="http://www.gpsvisualizer.com/"&gt;gpsvisualizer.com&lt;/a&gt; is one of them. It will give your map a semi-persistent URL so you can show it to your friends for a short time.&lt;/li&gt;
&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6151466317010516461?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6151466317010516461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/07/sharing-gps-tracks-from-tangogps-on.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6151466317010516461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6151466317010516461'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/07/sharing-gps-tracks-from-tangogps-on.html' title='Sharing GPS tracks from tangoGPS on Google Maps'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-8323746996406712280</id><published>2008-07-19T22:00:00.005-07:00</published><updated>2008-07-25T09:03:52.343-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='freerunner'/><title type='text'>Towards using the FreeRunner as my primary phone</title><content type='html'>&lt;p&gt;Having had some time to play around with the FreeRunner's software (&lt;a href="http://psung.blogspot.com/2008/07/freerunner-first-impressions.html"&gt;see my previous post&lt;/a&gt;), I can make a few more remarks about it now. By the way, if you are planning to get a FreeRunner (or if you have one), you should know that the &lt;a href="http://wiki.openmoko.org/"&gt;wiki&lt;/a&gt;, as well as the &lt;a href="http://lists.openmoko.org/mailman/listinfo/community"&gt;community&lt;/a&gt; and &lt;a href="https://lists.openmoko.org/mailman/listinfo/support"&gt;support&lt;/a&gt; mailing lists, are invaluable resources for figuring how to get things working or the best way to do something.&lt;/p&gt;
&lt;p&gt;First of all, having a phone that you can SSH into and do all the usual Linux-y stuff on is very, very, cool. When you plug the phone into your GNU/Linux computer it appears as a device on the other end of a new network interface &lt;tt&gt;usb0&lt;/tt&gt;. An SSH server is configured and works out of the box. You need to do a small amount of configuration to let your FreeRunner use your computer's connection to get to the internet.&lt;/p&gt;
&lt;p&gt;The FreeRunner also comes with a package manager (opkg) and a set of repositories from which you can easily install new software. The packages are changing fast and getting new fixes all the time. Software upgrading is as easy as: &lt;tt&gt;opkg update; opkg upgrade&lt;/tt&gt;. It's a snap to install new packages, too. I was delighted to be able to run Python on my phone.&lt;/p&gt;
&lt;p&gt;(Now, if only someone would port Emacs and develop an on-screen keyboard layout suitable for using it.)&lt;/p&gt;
&lt;p&gt;I installed a PDF reader and downloaded a couple of e-books to the phone. Astonishingly I can (pretty comfortably) read &lt;em&gt;pages formatted for printed books&lt;/em&gt; on the FreeRunner's screen.&lt;/p&gt;
&lt;p&gt;If you have been following the FreeRunner news you know that there are a bunch of software distributions you can choose from (at least three "official" ones as of this writing). This may seem worrisome but it's really not. My understanding is that all of the software distributions use the same repositories, merely installing different packages by default (e.g. the base apps and the launcher). From the standpoint of a software developer, you don't have to worry about painting yourself into a corner by choosing the "wrong" distribution: most apps should more or less run under all distributions. And from the standpoint of a user, reflashing your device is not difficult at all, if it turns out that a different distribution attains a critical mass. As long as you back up the good stuff (probably your home directory and parts of &lt;tt&gt;/etc&lt;/tt&gt;), you should be able to change distributions relatively painlessly.&lt;/p&gt;
&lt;p&gt;So, which distribution to choose? I've tried the 2007.2 image (the factory-installed software) and the ASU (a port of Qtopia to X11). The ASU will become the preferred distribution in the long term, and OpenMoko's attention is going there now. At this time, though, it feels a lot less slick in most places than the 2007.2 image. I can't make or receive phone calls with ASU and my current SIM card, which worked fine on 2007.2. The apps are more designed for a stylus rather than fingers. There is no terminal app, but that is expected to be addressed soon.&lt;/p&gt;
&lt;p&gt;If I can't find a quick resolution for the phone call problem, then I will probably go back to 2007.2. In either case, I plan to start using the FreeRunner as my primary phone. I'll also start to investigate options for writing quick apps to run on the phone. The more I play with the FreeRunner, the more I think about how those who can write code for the phone could modify or completely reinvent their workflows. Imagine having the adeptness of an Emacs whiz while working on your phone. That would make a general-purpose programmable phone an awesome device indeed.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Update:&lt;/b&gt; the PDF reader I'm using is &lt;a href="http://www.ginguppin.de/node/18"&gt;epdfview&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-8323746996406712280?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/8323746996406712280/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/07/towards-using-freerunner-as-my-primary.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8323746996406712280'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/8323746996406712280'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/07/towards-using-freerunner-as-my-primary.html' title='Towards using the FreeRunner as my primary phone'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-6486371634983170657</id><published>2008-07-15T18:39:00.004-07:00</published><updated>2008-07-25T09:03:52.344-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='freerunner'/><title type='text'>FreeRunner first impressions</title><content type='html'>&lt;p&gt;&lt;a href="http://openmoko.com/"&gt;OpenMoko&lt;/a&gt;'s FreeRunner went on sale on July 3. I ordered early that day and my FreeRunner arrived today.&lt;/p&gt;
&lt;p&gt;This is the only product I've ever felt compelled to take unboxing photos of:&lt;/p&gt;
&lt;p&gt;&lt;a style="text-decoration: none" href="http://web.psung.name/albums/freerunner/"&gt;&lt;img src="http://web.mit.edu/psung/Public/freerunner/thumbs/IMG_0237.JPG"&gt;&lt;br&gt;Click for FreeRunner unboxing photos&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;First of all, this thing is a lot tinier than I was expecting. It is not significantly larger or heavier than my current phone, a Razr. I suppose I should not be surprised because the last smaller-than-laptop device I purchased was a PDA back in the year 2001 or so. (I've never insisted on being at the cutting edge of mobile technology.)&lt;/p&gt;
&lt;p&gt;The texture is a lot like that on the outside of a Thinkpad.&lt;/p&gt;
&lt;p&gt;I haven't had much time to play with it except for charging it up and making a phone call (which worked, well). The screen is amazing, by the way&amp;mdash; higher resolution than that of pretty much any other phone-like or PDA-like device you can buy today.&lt;/p&gt;
&lt;p&gt;The software utilities that come with the phone are still in a state of churn, and it is not yet in a state where it can exercise all parts of the hardware reliably (GPS, etc.). As far as I am concerned, none of these things are deal-breakers. If you want to make the phone the best thing it can be, you had better start by removing all the man-made problems so people can work on solving &lt;em&gt;real&lt;/em&gt; problems. I wanted a phone with freedom, and that's what I am getting.&lt;/p&gt;
&lt;p&gt;One of my favorite things about OpenMoko is the people and the community spirit. You can really tell that this is not only a different kind of phone but also a different kind of company. Witness this exchange from the last week:&lt;/p&gt;
&lt;p&gt;Michael &amp;lt;simarillion&amp;gt;: can somebody tell me if I will lose my warranty when I open my Freerunner.&lt;br&gt;Sean Moss-Pultz &amp;lt;sean@openmoko.com&amp;gt;: [...] Do you really think we could get away with that kind of policy?! This is Openmoko. If you &lt;em&gt;don't&lt;/em&gt; open your Neo, you should probably have your warranty voided ;-)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-6486371634983170657?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/6486371634983170657/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/07/freerunner-first-impressions.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6486371634983170657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/6486371634983170657'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/07/freerunner-first-impressions.html' title='FreeRunner first impressions'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-270868640115331146</id><published>2008-06-26T13:48:00.002-07:00</published><updated>2010-09-29T22:11:02.557-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ubuntu'/><title type='text'>Living fearlessly with a laptop</title><content type='html'>&lt;p&gt;My Thinkpad X61s is tiny and powerful, so I like to take it places with me. Of course, when you go places with a laptop, there is a risk of it getting lost, broken, or stolen. For me (as for most people, I would guess) the integrity of the data on my laptop is far more valuable than the cost of the laptop itself. In fact, there are two measures I take which &lt;b&gt;almost entirely&lt;/b&gt; mitigate the risks of getting my laptop stolen (lost, broken, etc.). Consequently, I have become more willing to bring my laptop places. Here is what I do:&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Use hard disk encryption.&lt;/b&gt; The Alternate installers in Ubuntu and Debian give you the option of easily configuring an encrypted hard disk. Everything (except the &lt;tt&gt;/boot&lt;/tt&gt; partition, but even your swap) that goes onto the disk is transparently encrypted. You just need to type a password whenever you boot up your computer. There is some overhead associated with encrypting everything, but if you have more than one core you will rarely notice it.&lt;/p&gt;
&lt;p&gt;This means that, should your laptop fall into the wrong hands, no useful information whatsoever can be extracted from the hard disk.&lt;/p&gt;
&lt;p&gt;For this to work well, you need to lock your screen when you are not using it, and your computer needs to be configured to lock the screen when you wake from suspend. It should be noted that &lt;a href="http://www.freedom-to-tinker.com/?p=1257"&gt;some attacks have been described&lt;/a&gt; on hard disk encryption techniques. While the risk of these attacks remains low for most targets, if you are paranoid you would have to shut down (not just suspend) your computer before taking it places. You would also have to consider either overwriting the most sensitive areas of memory before you shutdown, or leaving your computer powered off for a couple of hours before taking it anywhere.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Keep backups.&lt;/b&gt; I do my backups over the internet so that I can backup from anywhere. I use a variant on the following script:&lt;/p&gt;
&lt;code&gt;rsync -vaxE --delete --ignore-errors --delete-excluded --filter="merge excluded-files" /home/phil/ remotehost:/path/to/backup/destination/&lt;/code&gt;
&lt;p&gt;where &lt;code&gt;excluded-files&lt;/code&gt; is a file that looks like this, and contains some paths that I don't want backed up (usually, local cache-like places that are generally space-consuming and not terribly useful):&lt;/p&gt;
&lt;code&gt;- /.local/share/Trash/&lt;br&gt;
- /.mozilla/firefox/*/Cache/&lt;br&gt;
- /.thumbnails/&lt;/code&gt;
&lt;p&gt;I run this about as often as I can remember to, and before I shut down my laptop to take it somewhere. That's all there is to it.&lt;/p&gt;
&lt;p&gt;With this measure, I can be quite confident that were my laptop to vaporize, I would lose nothing at all. It has the fortuitous side effect of making it super easy to reinstall an operating system.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-270868640115331146?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/270868640115331146/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/06/living-fearlessly-with-laptop.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/270868640115331146'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/270868640115331146'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/06/living-fearlessly-with-laptop.html' title='Living fearlessly with a laptop'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-970055329001593038.post-7657538074300080285</id><published>2008-06-24T20:10:00.002-07:00</published><updated>2008-07-25T09:04:07.924-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='git'/><title type='text'>Linus Torvalds on Git</title><content type='html'>&lt;p&gt;I finally got around to watching the &lt;a href="http://youtube.com/watch?v=4XpnKHJAok8"&gt;video&lt;/a&gt; of the tech talk that Linus gave at Google discussing the design of Git.&lt;/p&gt;
&lt;p&gt;In this video, Linus explains a lot of the advantages of using a distributed system. But it is also enlightening because it's a window into Linus's motivations: he discusses the ways in which his own needs&amp;mdash; as a system maintainer&amp;mdash; drove the design of the system, in particular in the areas of workflow, speed, and data integrity.&lt;/p&gt;
&lt;p&gt;One interesting idea is that in DVCS, the preferred development workflow (you pull from a small group of people you trust, who in turn pull from people they trust...) mirrors the way humans are wired to think about social situations. You cannot directly trust a huge group of people, but you can transitively trust many people via a web of trust&amp;mdash; a familiar concept from security. A centralized system cannot scale because there are &lt;em&gt;n&lt;/em&gt;&lt;sup&gt;2&lt;/sup&gt; pairs of conflicts waiting to happen, and they will happen, because groups of people are distributed (not everyone is in the same room at the same time on the same LAN). But a DVCS workflow can scale, because it is fundamentally based on interactions between people and not on the artificial technical requirement that there has to be a single canonical place for everything.&lt;/p&gt;
&lt;p&gt;Warning: Linus has strong opinions. I think he refers to at least three different groups of people as "ugly and stupid" in the course of his 70-minute talk.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/970055329001593038-7657538074300080285?l=psung.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://psung.blogspot.com/feeds/7657538074300080285/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://psung.blogspot.com/2008/06/linus-torvalds-on-git.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7657538074300080285'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/970055329001593038/posts/default/7657538074300080285'/><link rel='alternate' type='text/html' href='http://psung.blogspot.com/2008/06/linus-torvalds-on-git.html' title='Linus Torvalds on Git'/><author><name>Phil</name><uri>http://www.blogger.com/profile/12760478278391942483</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
