<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">
 
	<title>GFX::Monk</title>
	
	<link href="http://gfxmonk.net/" />
	<updated>2012-02-06T18:58:44+11:00</updated>
	<id>http://gfxmonk.net/</id>
	<author>
		<name>Tim Cuthbertson</name>
	</author>

	
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/gfxmonk" /><feedburner:info uri="gfxmonk" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site.</feedburner:browserFriendly><entry>
			<title>Cool projects I learnt about at lca2012</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/-Q71ut6b3Ro/cool-projects-i-learnt-about-at-lca2012.html" />
			<updated>2012-01-21T00:00:00+11:00</updated>
			<id>http://gfxmonk.net/2012/01/21/cool-projects-i-learnt-about-at-lca2012</id>
			<content type="html">
				&lt;p&gt;I went to &lt;a href="http://linux.conf.au/"&gt;linux.conf.au&lt;/a&gt; this week, and learnt about some pretty awesome tech (as well as hearing some entertaining, inspiring, touching and terrifying talks from the likes of Paul Fenwick, Bruce Perens, Karen Sandler and Jacob Appelbaum).&lt;/p&gt;

&lt;p&gt;So here&amp;rsquo;s a quick dump of cool projects I learnt about, with links where I could find them.&lt;/p&gt;

&lt;h4&gt;&lt;a href="https://browserid.org/"&gt;browser id&lt;/a&gt;:&lt;/h4&gt;

&lt;p&gt;Openid is not so great, due to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;usability / confusion (requiring a url as an id)&lt;/li&gt;
  &lt;li&gt;reliability (if your provider goes down, you can&amp;rsquo;t log in)&lt;/li&gt;
  &lt;li&gt;lock in, (hard for the user to migrate providers)&lt;/li&gt;
  &lt;li&gt;privacy (your provider knows &lt;em&gt;every&lt;/em&gt; url you log into, every time)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Browserid serves one simple purpose: to prove you own an email. It&amp;rsquo;s distributed. The browser, (not a third-party server) is the login intermediary.&lt;/p&gt;

&lt;p&gt;As an example: The login process to gmail generates a shortlived (in the order of hours or maybe days, I guess) cryptographically signed statement that you own that email, which your browser stores. Other sites just need to grab gmail&amp;rsquo;s public key and then they can themselves verify that the assertion you sent them proves you own (or can log in to) you@example.com.&lt;/p&gt;

&lt;p&gt;Demo site: &lt;a href="http:///myfavoritebeer.org"&gt;myfavoritebeer.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Not awesome &lt;em&gt;yet&lt;/em&gt;:
There&amp;rsquo;s no browser or email provider support. But it&amp;rsquo;s developed by mozilla, has scaffolding in js to work already in all browsers. Certs are stored on browserid.org for now, until browsers implement native support (so they are just as bad as a server intermediary, but only as a stopgap).&lt;/p&gt;

&lt;h4&gt;&lt;a href="http://arstechnica.com/business/news/2012/01/mozilla-demos-mediastream-processing-audio-mixing-in-firefox.ars"&gt;mediastreams processing api&lt;/a&gt;:&lt;/h4&gt;

&lt;p&gt;Very cool demos, which are online (although they require a dev build of firefox).&lt;/p&gt;

&lt;h4&gt;&lt;a href="https://developer.mozilla.org/en/CSS/calc"&gt;css calc()&lt;/a&gt;&lt;/h4&gt;
&lt;p&gt;Computation in css. Very cool. There are implementations in IE and Firefox so far, and work on webkit is in progress. This is not just a convenience like SASS and friends - it allows for previously impossible mixing of units like &lt;code&gt;100% - 10px&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;News on arbitrary metadata in git:&lt;/h4&gt;

&lt;p&gt;Apparently many people feel this is important for VCS interop (git-svn, fastimport, etc), and there are proposals for adding support (but it&amp;rsquo;s difficult to figure out how to do right in a way that won&amp;rsquo;t prohibit other useful things in the future).&lt;/p&gt;

&lt;h4&gt;openstack&lt;/h4&gt;

&lt;p&gt;Uses &lt;a href="http://cloud.ubuntu.com/2011/10/getting-started-with-ubuntu-orchestra-servers-in-concert/"&gt;orchestra&lt;/a&gt; by ubuntu for deployments.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://code.google.com/p/gerrit/"&gt;gerrit&lt;/a&gt; for code review. Use Jenkins plugins, pushes state notifications to launchpad.
openstack wrote a patch submission tool: git-review. Rebases &amp;amp; pushes patchset to gerrit.&lt;/p&gt;

&lt;h4&gt;testing ctdb&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://gitweb.samba.org/?p=autocluster.git;a=summary"&gt;Autocluster&lt;/a&gt; is a tool for testing clustered samba (and other things, presumably). Virtual kvm based clusters. Uses &lt;a href="http://libguestfs.org/guestfish.1.html"&gt;guestfish&lt;/a&gt; to manage volumes inside the kvm guests.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://dbench.samba.org/"&gt;dbench&lt;/a&gt; for automated performance tests. Can describe any kind of IO workload.&lt;/p&gt;

&lt;h4&gt;Assessing the potential impact of package updates&lt;/h4&gt;

&lt;p&gt;Tools for spelunking package relationships (on debian at least):
- Recursive depends, reverse depends, apt-cache, germinate.&lt;/p&gt;

&lt;h4&gt;misc projects / pointers&lt;/h4&gt;
&lt;p&gt;&lt;a href="http://sozi.baierouge.fr/wiki/en:welcome"&gt;sozi&lt;/a&gt; is an inkscape plugin for chopping up vectors into slide presentations.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://fossil-scm.org/index.html/doc/trunk/www/index.wiki"&gt;fossil scm&lt;/a&gt; is a VCS that tracks docs, wikis, bugs, etc in with the source code. Cool idea, apparently some bad implementation decisions though.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.safe-rm.org.nz/"&gt;safe-rm&lt;/a&gt;: replaces &lt;code&gt;rm&lt;/code&gt; and has a blacklist of folders you probably don&amp;rsquo;t really want to remove, such as &lt;code&gt;/usr/&lt;/code&gt;. No more bumblebeeing (can&amp;rsquo;t find the link, but there was once a bug in the bumblebee uninstall script that removed all of /usr as root).&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.labradoc.com/i/follower/p/android-arduino-handbag"&gt;handbag&lt;/a&gt; makes android accessory dev easy(er)&lt;/p&gt;

&lt;p&gt;&lt;a href="http://berrange.com/posts/2012/01/17/building-application-sandboxes-with-libvirt-lxc-kvm/"&gt;libvirt-sandbox&lt;/a&gt;: new library and command-line tools for app-level sandboxing with LCX and/or KVM. Should be coming in Fedora 17.&lt;/p&gt;

&lt;p&gt;Vsualisation: &lt;a href="http://www.gapminder.org/"&gt;gapminder.org&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://wiki.debian.org/FreedomBox"&gt;freedombox&lt;/a&gt;: 100% free tiny personal server project. Uses all open-source &amp;amp; federated social software like &lt;a href="https://joindiaspora.com/"&gt;diaspora&lt;/a&gt;, &lt;a href="http://buddycloud.com/"&gt;buddycloud&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://www.instamorph.com/"&gt;instamorph&lt;/a&gt;: malleable plastic that&amp;rsquo;s solid at room temperature, for making ad-hoc hooks, connectors, docks, etc. The aussie equivalent is apparently called &amp;ldquo;Polymorph&amp;rdquo;.&lt;/p&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/-Q71ut6b3Ro" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2012/01/21/cool-projects-i-learnt-about-at-lca2012.html</feedburner:origLink></entry>
	
		<entry>
			<title>Mentally ignoring files in git</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/sXX_l4onWzw/mentally-ignoring-files-in-git.html" />
			<updated>2011-11-15T00:00:00+11:00</updated>
			<id>http://gfxmonk.net/2011/11/15/mentally-ignoring-files-in-git</id>
			<content type="html">
				&lt;p&gt;For unfortunate reasons, at work we have intellij module files that are:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;checked into git (because they are useful and hard to recreate)&lt;/li&gt;
  &lt;li&gt;changing all the time for no good reason (because intellij is a bit like that)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the most part, the changes are just noise because paths, versions, etc. differ slightly across dev machines. Sometimes the differences are completely meaningless (unordered elements in a file being rearranged). But sometimes we &lt;em&gt;do&lt;/em&gt; want to check in new versions of these files, say when we add a new module.&lt;/p&gt;

&lt;p&gt;Since they are checked in, we can&amp;rsquo;t just add them to &lt;code&gt;.gitignore&lt;/code&gt;. But we can still mentally ignore them, with this rather ridiculous hack:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git status | sed -E -e 's/\x1b\[[0-9][12]m(.*\.iml)/'"`tput setaf 3`"'\1/'
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This changes the normally red (or green, or blue) lines in the &lt;code&gt;git status&lt;/code&gt; output to yellow instead when they refer to an intellij &lt;code&gt;.iml&lt;/code&gt; file. It&amp;rsquo;s completely hacky, but it&amp;rsquo;s better than breaking the build because you forgot to commit a file amongst all the noise.&lt;/p&gt;

&lt;p&gt;You can put this in a script you call instead of &lt;code&gt;git status&lt;/code&gt; - writing &lt;code&gt;git status&lt;/code&gt; takes too long anyway, I just call my script &lt;code&gt;g&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You&amp;rsquo;ll also need to make sure you have enabled colour &amp;ldquo;always&amp;rdquo; in &lt;code&gt;git status&lt;/code&gt; output, otherwise you&amp;rsquo;ll get no colours at all:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;$ git config --global color.status always
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;If anyone has a better way of ignoring files while having them checked in, I&amp;rsquo;d love to hear it. Do other VCSs allow you to deal with this any better?&lt;/p&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/sXX_l4onWzw" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/11/15/mentally-ignoring-files-in-git.html</feedburner:origLink></entry>
	
		<entry>
			<title>Obligate.js</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/l1QEGYI_Hzw/obligate-js.html" />
			<updated>2011-09-11T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/09/11/obligate-js</id>
			<content type="html">
				&lt;p&gt;I&amp;rsquo;ve been doing some browser-side javascript lately, and getting frustrated at the mess that is browser-side modules.. So here&amp;rsquo;s a tiny library that, given a tree containing javascript files, will give you a single javascript file containing &lt;em&gt;all&lt;/em&gt; of the modules, as well as a commonJS &lt;code&gt;require&lt;/code&gt; method to use in browser-side code. No more accidental globals, your variables are local and you just add your module&amp;rsquo;s public interface to properties on the module-local &lt;code&gt;exports&lt;/code&gt; object.&lt;/p&gt;

&lt;p&gt;Of course, it also includes a tool to grab all the javascript code of your own &lt;em&gt;and&lt;/em&gt; that of your recursive dependencies, specified in a &lt;a href="http://0install.net/"&gt;zero install&lt;/a&gt; feed.&lt;/p&gt;


				
				
					&lt;p&gt;&lt;a href="http://gfxmonk.net/dist/0install/obligate.js.xml"&gt;(view link)&lt;/a&gt;&lt;/p&gt;
				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/l1QEGYI_Hzw" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/09/11/obligate-js.html</feedburner:origLink></entry>
	
		<entry>
			<title>Ruby's split() function makes me feel special (in a bad way)</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/HgXtytzCjEY/ruby-s-split-function-makes-me-feel-special-in-a-bad-way.html" />
			<updated>2011-09-04T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/09/04/ruby-s-split-function-makes-me-feel-special-in-a-bad-way</id>
			<content type="html">
				&lt;p&gt;Quick hand count: who knows what &lt;code&gt;String.split()&lt;/code&gt; does?&lt;/p&gt;

&lt;p&gt;Most developers probably do. Python? easy. Javascript? probably. But if you&amp;rsquo;re a ruby developer, chances are close to &lt;code&gt;nil&lt;/code&gt;. I&amp;rsquo;m not trying to imply anything about the intelligence or skill of ruby developers, it&amp;rsquo;s just that the odds are stacked against you.&lt;/p&gt;

&lt;hr /&gt;

&lt;h2&gt;So, what does &lt;code&gt;String.split()&lt;/code&gt; do?&lt;/h2&gt;

&lt;p&gt;In the simple case, it takes a separator string. It returns an array of substrings, split on the given string. Like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;py&amp;gt; "one|two|three".split("|")
["one", "two", "three"]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Simple enough. As an extension, some languages allow you to pass in a &lt;code&gt;num_splits&lt;/code&gt; option. In python, it splits only this many times, like so:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;py&amp;gt; "one|two|three".split("|", 1)
["one", "two|three"]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Ruby is similar, although you have to add one to the second argument (it talks about number of returned components, rather than number of splits performed).&lt;/p&gt;

&lt;p&gt;Javascript is a bit odd, in that it will ignore the rest of the string if you limit it:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;js&amp;gt; "one|two|three".split("|", 2)
["one", "two"]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I don&amp;rsquo;t like the javascript way, but these are all valid interpretations of &lt;code&gt;split&lt;/code&gt;. So far. And that&amp;rsquo;s pretty much all you have to know for python and javascript. But ruby? Pull up a seat.&lt;/p&gt;

&lt;!-- more --&gt;

&lt;hr /&gt;

&lt;h2&gt;Special cases.&lt;/h2&gt;
&lt;p&gt;a.k.a &lt;em&gt;surprises&lt;/em&gt;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;irb&amp;gt; "one||two||three".split("|")
=&amp;gt; ["one", "", "two", "", "three"]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Seems reasonable. But:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;irb&amp;gt; "one  two  three".split(" ")
=&amp;gt; ["one", "two", "three"]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Note there are double spaces in the input - &lt;strong&gt;ruby&amp;rsquo;s split has different behaviour if the separator is a single space character&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;But if you don&amp;rsquo;t like that, you can use a regex!&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;irb&amp;gt; "one  two  three".split(/ /)
=&amp;gt; ["one", "", "two", "", "three"]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Theoretically this has the same meaning, but you get different behaviour!&lt;/p&gt;

&lt;p&gt;The stupid thing about this example is that there is absolutely no need to treat &lt;code&gt;' '&lt;/code&gt; as a special case - you can achieve the same behaviour &lt;em&gt;explicitly&lt;/em&gt; if you actually want it, by using &lt;code&gt;/s+/&lt;/code&gt; as the separator.&lt;/p&gt;

&lt;p&gt;And how about:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;irb&amp;gt; "||one||two||three||".split("|")
=&amp;gt; ["", "", "one", "", "two", "", "three"]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;ruby&amp;rsquo;s split treats &lt;em&gt;leading&lt;/em&gt; blanks differently to &lt;em&gt;trailing&lt;/em&gt; blanks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;unless&lt;/strong&gt; you include a &lt;em&gt;negative&lt;/em&gt; number as the &lt;code&gt;num_splits&lt;/code&gt; argument - in that case it has no effect but its &lt;em&gt;sign&lt;/em&gt; changes the behaviour of split to include trailing blanks:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;irb&amp;gt; "||one||two||three||".split("|", -2)
=&amp;gt; ["", "", "one", "", "two", "", "three", "", ""]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;(note that there is no way to enable this behaviour &lt;em&gt;and&lt;/em&gt; limit the number of splits performed).&lt;/p&gt;

&lt;p&gt;I can see no useful purpose for this special case. And again, if I actually &lt;em&gt;wanted&lt;/em&gt; this behaviour, it would be easy enough to implement. In fact I would still implement it in order to correctly convey intent instead of relying on poorly-known edge cases of the ruby standard library.&lt;/p&gt;

&lt;p&gt;By the way, these are not accidents - they are &lt;a href="http://ruby-doc.org/core/classes/String.html#M001165"&gt;documented&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For bonus points, the two special cases outlined here can interact in fun ways. I didn&amp;rsquo;t mention it above, but splitting on a single space &lt;em&gt;also&lt;/em&gt; ignores leading and trailing whitespace (also known as &lt;code&gt;strip&lt;/code&gt;, if you actually &lt;em&gt;want&lt;/em&gt; that behaviour). If you wanted to preserve those, you might try the negative number trick from above. But what does that give you?&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;irb&amp;gt; "  a  b  c  ".split(" ", -1)
=&amp;gt; ["a", "b", "c", ""]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;What a mess.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;So, have you got all that? Are you going to remember it next time you use &lt;code&gt;split&lt;/code&gt;? I doubt it (I just wrote about it in depth, and I&amp;rsquo;ll still probably forget). And don&amp;rsquo;t forget to think about how these special cases could interact with the myriad of &lt;em&gt;other&lt;/em&gt; special cases and surprising behaviour in ruby.&lt;/p&gt;

&lt;p&gt;You might think that I&amp;rsquo;m just picking on ruby - this could happen in any language. But one of the reasons I like python so much is that not only is the language itself simple and elegant, but the community largely agrees upon some very fundamental ideas - &lt;a href="http://www.python.org/dev/peps/pep-0020/"&gt;the zen of python&lt;/a&gt;. These are more guiding principles than laws, but they are usually respected unless you have a good reason not to (and you probably don&amp;rsquo;t).&lt;/p&gt;

&lt;p&gt;These points in particular all seem pretty relevant:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Simple is better than complex.&lt;/li&gt;
  &lt;li&gt;Special cases aren&amp;rsquo;t special enough to break the rules.&lt;/li&gt;
  &lt;li&gt;If the implementation is hard to explain, it&amp;rsquo;s a bad idea.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I guess if you disagree with those, ruby might well be for you.&lt;/p&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/HgXtytzCjEY" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/09/04/ruby-s-split-function-makes-me-feel-special-in-a-bad-way.html</feedburner:origLink></entry>
	
		<entry>
			<title>Node.js child processes</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/T-4eZhCHyCM/node-js-child-processes.html" />
			<updated>2011-09-02T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/09/02/node-js-child-processes</id>
			<content type="html">
				&lt;p&gt;&lt;strong&gt;me&lt;/strong&gt;: Hey &lt;a href="http://nodejs.org/"&gt;node&lt;/a&gt;, how can I tell if my &lt;code&gt;child_process.spawn()&lt;/code&gt; call failed before it even runs the desired command? Is there a return value? An exception? Maybe there&amp;rsquo;s an error event I can listen for?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;node&lt;/strong&gt;: Even better! Here&amp;rsquo;s &lt;a href="http://nodejs.org/docs/v0.4.11/api/all.html#child_process.spawn"&gt;an example from the documentation&lt;/a&gt; to do exactly that:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;var spawn = require('child_process').spawn,
    child = spawn('bad_command');

child.stderr.setEncoding('utf8');
child.stderr.on('data', function (data) {
  if (/^execvp\(\)/.test(data)) {
    console.log('Failed to start child process.');
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;me&lt;/strong&gt;: Thanks, that&amp;rsquo;s&amp;hellip; That&amp;rsquo;s just stunning.&lt;/p&gt;

&lt;p&gt;(For extra points, this doesn&amp;rsquo;t even work if the child process inherits &lt;code&gt;stderr&lt;/code&gt;, as my actual code does. Is this just a silly example from the documentation, or is there really nothing better?)&lt;/p&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/T-4eZhCHyCM" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/09/02/node-js-child-processes.html</feedburner:origLink></entry>
	
		<entry>
			<title>Stereoscoper and the Depth of Awesomeness</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/nvbQOOYVg28/stereoscoper-and-the-depth-of-awesomeness.html" />
			<updated>2011-08-29T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/08/29/stereoscoper-and-the-depth-of-awesomeness</id>
			<content type="html">
				&lt;p&gt;A few days ago I got a shiny new toy: a 3d camera from thinkgeek (I&amp;rsquo;d link to it, but it seems to have disappeared from their catalogue).
I&amp;rsquo;m a massive fan of 3d photos / video, so it&amp;rsquo;s pretty cool to have a device that allows me to take stereoscopic photo pairs simultaneously (you can do it manually with a static scene, but those get boring).&lt;/p&gt;

&lt;p&gt;Sadly (although not surprisingly), the quality is not great. The limited resolution is not really an issue given how you&amp;rsquo;re likely to view them, but the pictures come out awkwardly stretched to half the expected horizontal resolution. They are also pre-combined in a single JPEG, they are the way around for cross-eyed viewing, and the colour balance is frequently off between the two sensors (which can be really jarring).&lt;/p&gt;

&lt;p&gt;Seeing a lot of manual photo fixing in my future, I set out to automate it. And thus &lt;a href="https://github.com/gfxmonk/stereoscoper"&gt;stereoscoper&lt;/a&gt; was born, as a way to bulk-convert stereo images to other formats. Aside from the obvious geometry changes (the horizontal resolution and image placement), I also learnt all about &lt;a href="http://en.wikipedia.org/wiki/Histogram_matching"&gt;histogram matching&lt;/a&gt; in order to make the colour balance consistent across stereo pairs. And in order to make animated gifs that match up nicely, there&amp;rsquo;s even an interactive mode where you can fine-tune the alignment of the image pairs.&lt;/p&gt;

&lt;p&gt;In the wiggly-animated spirit of &lt;a href="http://3erd.tumblr.com/"&gt;3ERD&lt;/a&gt; (note: some images there are NSFW), here&amp;rsquo;s some fun we had in the park with my new toy:&lt;/p&gt;

&lt;p&gt;(click to toggle each animation. It&amp;rsquo;s off by default to save your brain from having a fit ;)&lt;/p&gt;

&lt;p class="center"&gt;&lt;a href="/images/photo_3d_park_jump2.gif"&gt;&lt;img width="400" height="299" class="toggle" src="/images/photo_3d_park_jump2-still.gif" /&gt;&lt;/a&gt;   &lt;a href="/images/photo_3d_park_jump2.jpg"&gt;(stereo)&lt;/a&gt;&lt;/p&gt;
&lt;p class="center"&gt;&lt;a href="/images/photo_3d_park_jump3.gif"&gt;&lt;img width="400" height="299" class="toggle" src="/images/photo_3d_park_jump3-still.gif" /&gt;&lt;/a&gt;   &lt;a href="/images/photo_3d_park_jump3.jpg"&gt;(stereo)&lt;/a&gt;&lt;/p&gt;
&lt;p class="center"&gt;&lt;a href="/images/photo_3d_park_juggle1.gif"&gt;&lt;img width="400" height="299" class="toggle" src="/images/photo_3d_park_juggle1-still.gif" /&gt;&lt;/a&gt; &lt;a href="/images/photo_3d_park_juggle1.jpg"&gt;(stereo)&lt;/a&gt;&lt;/p&gt;
&lt;p class="center"&gt;&lt;a href="/images/photo_3d_park_dog.gif"&gt;&lt;img width="400" height="299" class="toggle" src="/images/photo_3d_park_dog-still.gif" /&gt;&lt;/a&gt;     &lt;a href="/images/photo_3d_park_dog.jpg"&gt;(stereo)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: Click the (stereo) link under each image for a cross-eyed viewing version.&lt;/p&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/nvbQOOYVg28" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/08/29/stereoscoper-and-the-depth-of-awesomeness.html</feedburner:origLink></entry>
	
		<entry>
			<title>Experiment: Using Zero-Install as a Plugin Manager</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/x6tslqnzCQM/using-zero-install-as-a-plugin-manager.html" />
			<updated>2011-08-02T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/08/02/using-zero-install-as-a-plugin-manager</id>
			<content type="html">
				&lt;p&gt;So for a little while now I&amp;rsquo;ve been wanting to try an experiment, using &lt;a href="http://0install.net"&gt;Zero Install&lt;/a&gt; as a Plugin Manager. Some background:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Zero install is designed to be used for distributing applications and libraries.&lt;/li&gt;
  &lt;li&gt;One of its greatest strengths is that it has no global state, and doesn&amp;rsquo;t require elevated privileges (i.e root) to run a program (and as the name implies, there is no installation to speak of).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since there&amp;rsquo;s no global state, it seems possible to use this as a dependency manager &lt;em&gt;within&lt;/em&gt; a program - also known as a plugin system.&lt;/p&gt;

&lt;p&gt;Happily, it turns out it&amp;rsquo;s not so difficult. There are a few pieces required to set it up, but for the most part they are reusable - and much simpler to implement (and more flexible) than most home-rolled plugin systems.&lt;/p&gt;

&lt;!-- more --&gt;
&lt;p&gt;(&lt;em&gt;note: this article makes use of features in zero install version 0.52. If you are trying to run the examples, you will need that version or later. Fortunately, 0install can be easily bootstrapped by running &lt;code&gt;0launch http://0install.net/2007/interfaces/ZeroInstall.xml &amp;lt;interface&amp;gt;&lt;/code&gt;&lt;/em&gt;)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note to program authors:&lt;/strong&gt; This article is an explanation and rationale of the techniques I&amp;rsquo;ve used to manage plugins with zeroinstall. If you simply want to enable plugins for your own zeroinstall feed, you may want to skip to the documentation for &lt;a href="/dist/0install/zeroinstall-plugin-manager.xml"&gt;zeroinstall-plugin-manager&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;Background:&lt;/h1&gt;

&lt;p&gt;&lt;a href="http://somethingaboutorange.com/mrl/projects/nose/"&gt;nosetests&lt;/a&gt; is an extensible test runner for python. I think it&amp;rsquo;s great, and have written a number of plugins for it. It has a built-in plugin system that relies on &lt;a href="http://stackoverflow.com/questions/774824/explain-python-entry-points"&gt;setuptools entry points&lt;/a&gt;, which annoys me because it means I have to package and install my plugins using setuptools, which is not a very good dependency manager for at least these reasons:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;it only works for python&lt;/li&gt;
  &lt;li&gt;packages are installed globally, and there can be only one &amp;ldquo;active&amp;rdquo; version&lt;sup id="fnref:virtualenv"&gt;&lt;a href="#fn:virtualenv" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
  &lt;li&gt;it can&amp;rsquo;t uninstall anything (this is pretty rubbish)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That&amp;rsquo;s why I want to use 0install to publish and manage nosetests plugins.&lt;/p&gt;

&lt;h1&gt;The basics - every user gets their own feed:&lt;/h1&gt;

&lt;p&gt;A zero install feed has two important parts: The implementation, and the dependencies. For nosetests itself, it doesn&amp;rsquo;t really have dependencies. But if you consider a user&amp;rsquo;s own set of preferred plugins, that&amp;rsquo;s really just a list of packages that you want nosetets to know about. Nosetests isn&amp;rsquo;t directly dependent upon them, but the conceptual package of &amp;ldquo;Tim&amp;rsquo;s preferred nosetests plugins&amp;rdquo; does.&lt;/p&gt;

&lt;p&gt;So we&amp;rsquo;ll start with a local 0install feed to represent the user&amp;rsquo;s preferred set of plugins. This allows us to list nosetests as the &amp;ldquo;runner&amp;rdquo;, while depending on whatever additional plugins we want nosetests to know about. This will be specific to the user, and will never be published (it doesn&amp;rsquo;t even need a URI).&lt;/p&gt;

&lt;p&gt;Here&amp;rsquo;s the relevant excerpt from my own such feed:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;group&amp;gt;
  &amp;lt;command name="run"&amp;gt;
    &amp;lt;runner interface="http://gfxmonk.net/dist/0install/nosetests-plugin-resolver.xml"/&amp;gt;
  &amp;lt;/command&amp;gt;
  &amp;lt;requires interface="http://gfxmonk.net/dist/0install/rednose.xml"/&amp;gt;
&amp;lt;/group&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That just says &amp;ldquo;use the &lt;code&gt;nosetests-plugin-resolver&lt;/code&gt; to run this feed, and make sure the &lt;a href="/dist/0install/rednose.xml"&gt;rednose&lt;/a&gt; plugin is made available&amp;rdquo;. Observant readers will notice that I originally said we could use nosetests itself as a runner, so what&amp;rsquo;s this plugin resolver thing about?&lt;/p&gt;

&lt;h1&gt;Making plugins known to nosetests at runtime&lt;/h1&gt;

&lt;p&gt;Setuptools provides an entry point mechanism for python programs to discover plugins that have registered an implementation for certain well-known entry points. This is done using a setuptools-specific API, and mandates that all plugins must also use setuptools. In other words, we can&amp;rsquo;t re-use that. But it&amp;rsquo;s not too hard to make our own.&lt;/p&gt;

&lt;p&gt;Zero Install allows packages one main way of allowing packages to know about other packages: environment variables. It&amp;rsquo;s a simple mechanism, and works well with existing systems - for example, if you write a python library, you just have to add it to &lt;code&gt;$PYTHONPATH&lt;/code&gt;. If you want something to be runnable, you add it to &lt;code&gt;$PATH&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So all we need to do is:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Put our plugin&amp;rsquo;s name into an environment variable&lt;/li&gt;
  &lt;li&gt;Make a plugin loader that can use this environment variable to load plugins (this takes the place of setuptools&amp;rsquo; entry point loader)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first one is trivial. In the feed for &lt;a href="/dist/0install/rednose.xml"&gt;rednose&lt;/a&gt;, we just include:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&amp;lt;environment name="NOSETESTS_PLUGINS" value="rednose/RedNose"/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;That will tell our plugin resolver to perform the equivalent of:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;from rednose import RedNose
plugins.append(RedNose())
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The implementation of the plugin loader (#2) is reasonably unexciting. It simply parses a PATH-like &lt;code&gt;$NOSETESTS_PLUGINS&lt;/code&gt; variable, imports each plugin (using &lt;code&gt;__import__&lt;/code&gt;), and hands control over to nosetests itself. For the sake of reusability I&amp;rsquo;ve pulled the entry-point-like mechanism of instantiating objects from an environment variable into a &lt;a href="/dist/0install/python-env-importer.xml"&gt;helper library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that if support for loading plugins from environment variables can be added to nosetests proper, there will be no need for this &lt;code&gt;nosetests-plugin-resolver&lt;/code&gt; wrapper. And indeed if you are using this mechanism for your own program, you shouldn&amp;rsquo;t need one either.&lt;/p&gt;

&lt;h1&gt;Making it useable&lt;/h1&gt;

&lt;p&gt;So now we have all of the functional pieces, but it&amp;rsquo;s not very user-friendly. We don&amp;rsquo;t want the user to have to be an expert at editing zero-install xml feed files, so we&amp;rsquo;ll need a simple &lt;strong&gt;runner&lt;/strong&gt; that puts together the feed for the user. This program must:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;load a persisted list of plugins (implemented as a file in ~/.config with one URI per line)&lt;/li&gt;
  &lt;li&gt;add or remove plugins from this set (if &amp;ndash;plugin-add or &amp;ndash;plugin-remove options are given)&lt;/li&gt;
  &lt;li&gt;compose a local XML feed, using a template and adding in a &lt;code&gt;&amp;lt;requires&amp;gt;&lt;/code&gt; element for each requested plugin&lt;/li&gt;
  &lt;li&gt;ask 0install to launch the feed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The runner could modify a 0install file directly, but I think managing a simple file with one URI per line is a much simpler proposition.&lt;/p&gt;

&lt;p&gt;In order to help with this, I&amp;rsquo;ve created &lt;a href="/dist/0install/zeroinstall-plugin-manager.xml"&gt;zeroinstall-plugin-manager&lt;/a&gt;. If your requirements aren&amp;rsquo;t terribly demanding, you can simply use it as a &lt;code&gt;&amp;lt;runner&amp;gt;&lt;/code&gt; for your own feed and move your actual functionality to the &lt;code&gt;core&lt;/code&gt; command of your feed (instead of the default &lt;code&gt;run&lt;/code&gt;). If you require more control, it&amp;rsquo;s an importable python module you can use to do the heavy lifting of maintaining the configuration and generating the user-specific feed file.&lt;/p&gt;

&lt;h1&gt;Summary: the final setup&lt;/h1&gt;

&lt;p&gt;So after all this, we have three pieces to our puzzle:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href="/dist/0install/nosetests-runner.xml"&gt;nosetests-runner.xml&lt;/a&gt; - this is the feed that is actually run by the user, and contains the code to load plugins from environment variables and then pass control to nosetests proper.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href="/dist/0install/zeroinstall-plugin-manager.xml"&gt;zeroinstall-plugin-manager.xml&lt;/a&gt; - this is the &lt;code&gt;&amp;lt;runner&amp;gt;&lt;/code&gt; for nosetests-runner.xml, and it processes the plugin options before passing control back to nosetests-runner (with user-specific plugins as additional dependencies).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;a href="/dist/0install/nose.xml"&gt;nose.xml&lt;/a&gt; - this is just a zero-install feed for the official nosetests package&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Again, if you can add the plugin-loading features from nosetests-runner to nosetests itself, there would be no need to publish two separate feeds - it&amp;rsquo;s just needed in the case where the original program can&amp;rsquo;t load plugins from environment variables.&lt;/p&gt;

&lt;h1&gt;Benefits&lt;/h1&gt;

&lt;p&gt;So what do we actually gain from using zero install?&lt;/p&gt;

&lt;p&gt;Specifically for nosetests, we gain a lot of freedom:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You can use and publish nosetests plugins without having to use setuptools.
    &lt;ul&gt;
      &lt;li&gt;You don&amp;rsquo;t have to use zero-install either, as long as your preferred system can add to &lt;code&gt;$NOSETESTS_PLUGINS&lt;/code&gt;.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Plugins are not installed globally, and are only loaded when required by either the program under test or the user&amp;rsquo;s preference.
    &lt;ul&gt;
      &lt;li&gt;This reduces the chance of conflicting plugins.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;You can easily stop using a plugin temporarily to diagnose problems.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And in general, for &lt;em&gt;any&lt;/em&gt; program that uses 0install to manage plugins, you get:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A robust dependency manager that can deal with not just inter-dependent plugins, but also plugins that require native libraries or libraries written in another language.&lt;/li&gt;
  &lt;li&gt;Developers can use a feed that runs your application with the required plugins for their project as dependencies, saving end-users from having to manually install / remove plugins.&lt;/li&gt;
  &lt;li&gt;&lt;a href="http://zero-install.sourceforge.net/0test.html"&gt;0test&lt;/a&gt; can test multiple versions of your app automatically, even if different versions have conflicting plugin dependencies.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;Results&lt;/h1&gt;

&lt;p&gt;I may not be able to convince the author of nosetests to use this new system instead of the setuptools-based approach (since setuptools is so widely used in the python community), but nonetheless as an experiment it&amp;rsquo;s shown that zero install can work quite well as a plugin manager. No knowledge of zero install is required to use it, and developers get the benefits of a general-purpose dependency manager instead of the quirks of rolling your own plugin system. I strongly suggest that anyone looking to add a plugin system to an application take a look at zero install.&lt;/p&gt;

&lt;h1&gt;Extending to other software: Gnome Shell&lt;/h1&gt;

&lt;p&gt;To show that this is really not a hard thing to apply to other projects, I&amp;rsquo;ll give another example using Gnome Shell, the new user interface for Gnome 3. I have a vested interest in using zero install for gnome shell, as I have published an extension (&lt;a href="/shellshape/"&gt;shellshape&lt;/a&gt;) that relies upon a custom fork of &lt;code&gt;mutter&lt;/code&gt; (which the existing extension system cannot support).&lt;/p&gt;

&lt;p&gt;So, how hard was it to add zeroinstall extensions to gnome shell? Pretty easy - since gnome-shell is already a good citizen using &lt;code&gt;$XDG_DATA_DIRS&lt;/code&gt; to find extensions, there was no code modification needed. It&amp;rsquo;s also an excellent example of the benefits of zero install, since the manual (user-level) installation process is downright awful for extensions that need their own gsettings schemas (it&amp;rsquo;s possible, though I&amp;rsquo;ve never seen anything but discouragement for those who would like to).&lt;/p&gt;

&lt;p&gt;To use this system without any modifications to gnome-shell, you can simply run:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;0launch \
	http://gfxmonk.net/dist/0install/zeroinstall-plugin-manager.xml \
	--plugin-command run \
	http://gfxmonk.net/dist/0install/gnome-shell.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Obviously, this is better used as a &lt;code&gt;&amp;lt;runner&amp;gt;&lt;/code&gt;&lt;sup id="fnref:package-feed"&gt;&lt;a href="#fn:package-feed" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt; - the above script is just to demonstrate that this mechanism requires no code modifications. I&amp;rsquo;ve also started using this runner for &lt;a href="/shellshape/"&gt;shellshape&lt;/a&gt;, because that&amp;rsquo;s become my gnome-shell replacement.&lt;/p&gt;

&lt;p&gt;Two examples that use this mechanism already are my own &lt;a href="/dist/0install/shellshape.xml"&gt;shellshape.xml&lt;/a&gt;, and the much simpler &lt;a href="http://gfxmonk.net/dist/0install/gnome-shell-updateindicator.xml"&gt;gnome-shell-updateindicator.xml&lt;/a&gt; feed I created for &lt;a href="https://launchpad.net/updateindicator"&gt;updateindicator&lt;/a&gt;.&lt;/p&gt;

&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:virtualenv"&gt;
      &lt;pre&gt;&lt;code&gt;        Virtualenv and friends can help with non-global python packages and I fully recommend doing so, but it's still a hack (and requires too much effort from the user).
&lt;/code&gt;&lt;/pre&gt;
      &lt;p&gt;&lt;a href="#fnref:virtualenv" rev="footnote"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:package-feed"&gt;
      &lt;pre&gt;&lt;code&gt;      I'd add the `&amp;lt;runner&amp;gt;` to gnome-shell itself, except that it's a package implementation and for technical reasons these can't make use of `&amp;lt;runner&amp;gt;`s.
&lt;/code&gt;&lt;/pre&gt;
      &lt;p&gt;&lt;a href="#fnref:package-feed" rev="footnote"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/x6tslqnzCQM" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/08/02/using-zero-install-as-a-plugin-manager.html</feedburner:origLink></entry>
	
		<entry>
			<title>Tame.JS: Async Flow Control</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/zRPeGhS4VpI/tame-js-async-flow-control.html" />
			<updated>2011-07-19T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/07/19/tame-js-async-flow-control</id>
			<content type="html">
				&lt;p&gt;If you are interested in my &lt;a href="/2010/07/04/defer-taming-asynchronous-javascript-with-coffeescript.html"&gt;defer&lt;/a&gt; work with async control flow in CofeeScript, you&amp;rsquo;ll probably be interested in &lt;a href="http://okws.org/doku.php?id=sfslite:tame2"&gt;Tame.JS&lt;/a&gt;. The guys from OkCupid have a history with this sort of thing, apparently they have been using &lt;a href="http://okws.org/doku.php?id=sfslite:tame2"&gt;a similar mechanism they built for C++&lt;/a&gt; for years.&lt;/p&gt;

&lt;p&gt;Tame allows for more explicit control over parallelism than &lt;code&gt;defer&lt;/code&gt;, and is a pretty simple mechanism. Contrasted to &lt;a href="http://onilabs.com/stratifiedjs"&gt;Stratified JS&lt;/a&gt; it seems to be simpler and more interoperable with existing javascript codebases, but also has fewer features - Tame.js is at a similar level to &lt;code&gt;defer&lt;/code&gt;, while Stratified JS offers additional features like promise values (strata), parallel composition, alternative composition and more.&lt;/p&gt;

&lt;p&gt;Regardless of which you prefer, it&amp;rsquo;s good to see people tackling the problem despite the common wisdom seeming to be that there is no problem (or worse, that it can be adequately addressed with libraries alone).&lt;/p&gt;

&lt;p&gt;As usual, there&amp;rsquo;s some good commentary going on at &lt;a href="http://news.ycombinator.com/item?id=2776938"&gt;hacker news&lt;/a&gt;. There are even a bunch of people wondering when such a useful mechanism will arrive in CoffeeScript ;)&lt;/p&gt;


				
				
					&lt;p&gt;&lt;a href="http://tamejs.org/"&gt;(view link)&lt;/a&gt;&lt;/p&gt;
				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/zRPeGhS4VpI" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/07/19/tame-js-async-flow-control.html</feedburner:origLink></entry>
	
		<entry>
			<title>Personas: The Missing Piece of Google+ Relationships</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/QMHA00irVgE/personas-the-missing-piece-of-google-relationships.html" />
			<updated>2011-07-09T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/07/09/personas-the-missing-piece-of-google-relationships</id>
			<content type="html">
				&lt;p&gt;I&amp;rsquo;ve been playing with Google+ for a little while, and think that circles (and the emphasis on using them to manage your relationships) is an excellent approach. But it still seems to me like half of the equation is missing.&lt;/p&gt;

&lt;h3&gt;In the Beginning, Friends Were Binary (and Mutual)&lt;/h3&gt;

&lt;p&gt;In Facebook, you are friends or you are not. And worse, you can only be friends if both participants &lt;em&gt;agree&lt;/em&gt; to be friends. That might well represent close friends reasonably well, but that&amp;rsquo;s not what Facebook is used for a lot of the time, and it makes it pretty awkward when you have to decide whether to refuse someone friendship status just because you don&amp;rsquo;t really want to be inundated with their updates.&lt;/p&gt;

&lt;h3&gt;Asymmetric, Contextual Relationships&lt;/h3&gt;

&lt;p&gt;Google+ circles allow me, the viewer, to group you. I can group you by context (work, geek, etc) or by closeness (friend, acquaintance, etc). I can put you in multiple groups. I don&amp;rsquo;t have to get your permission, and you don&amp;rsquo;t even know what groups I&amp;rsquo;ve put you in. When I post, I can share with groups, and when I read posts, I can filter by group. This is all pretty splendid, because it supports a more nuanced view of relations more than just a boolean &amp;ldquo;friend&amp;rdquo; status.&lt;/p&gt;

&lt;p&gt;But it&amp;rsquo;s only half of the equation. I can say that you are my close friend &lt;em&gt;and&lt;/em&gt; that you are a poster of excellent geeky links, but that simply drops you wholesale into both of those contexts. I see everything that you share with me, in any context that I have placed you.&lt;/p&gt;

&lt;p&gt;People aren&amp;rsquo;t like that. People share a number of things, for a number of reasons. I post &lt;strike&gt;dumb&lt;/strike&gt; &lt;em&gt;humorous&lt;/em&gt; quips. I post boring status updates about my sandwich and its contents. I post about political issues. I post timely banter filled with inside references to my close friends. And most frequently of all, I post about technology.&lt;/p&gt;

&lt;p&gt;Now, I know for a fact that not everybody wants to see all of that. My high-school friends don&amp;rsquo;t care about inside jokes, but may well care about big events like my career, travel adventures, moving, etc. People who follow me for my relentless but insightful bashing of ruby and javascript probably don&amp;rsquo;t give a damn about my personal life, and may or may not care about my views on current political events. Not to mention that the current system places the same importance on &amp;ldquo;I have a sandwich&amp;rdquo; as &amp;ldquo;I have a baby&amp;rdquo; (I&amp;rsquo;m sure the latter would receive more attention, but the posts alone aren&amp;rsquo;t represented any differently).&lt;/p&gt;

&lt;p&gt;I could use circles for this, in theory. I could send my humorous quips to those who find me funny, my geeky links to those who would be interested in them, and my discussions of sandwich contents to those I presume to be exceedingly bored. But that&amp;rsquo;s close to impossible for me to get right (even if I do, people&amp;rsquo;s preferences are bound to change without them telling me) and doesn&amp;rsquo;t deal with twitter-style followers at all - what if my geeky links are so great that people I&amp;rsquo;ve never added to a circle wish to read them? I have no problem with that, and yet circles encourages me to share those things with only those who I think would like them (or else post them too broadly, annoying my friends who don&amp;rsquo;t care for masses of geeky links).&lt;/p&gt;

&lt;p&gt;Even those friends who &lt;em&gt;do&lt;/em&gt; care about all of my posts probably don&amp;rsquo;t want to see them everywhere. If you&amp;rsquo;re checking up what&amp;rsquo;s going on in the lives of your friends, you don&amp;rsquo;t really want to see links to ranting articles about the state of the patent system or discussions over which is the true circle constant. And yet maybe you &lt;em&gt;do&lt;/em&gt; want to see that when you&amp;rsquo;re cruising through your tech friends&amp;rsquo; posts.&lt;/p&gt;

&lt;h3&gt;Personas: Two-Way Sharing Control&lt;/h3&gt;

&lt;p&gt;Blogs and other sites will often address this issue with tags or categories. If you have great opinions on programming but are an insufferable git when you ramble on about sports, I will happily just subscribe to your &lt;code&gt;programming&lt;/code&gt; tagged posts. Personas serve the same purpose, on a personal level. A blog has categories, I have personas. Instead of forcing me to carefully pick my audience, let the choice be two-way. I&amp;rsquo;ll share as broadly as I feel comfortable, and you can view my updates only so far as they interest you. You get a more relevant stream of information, and I don&amp;rsquo;t have to self-censor so as to not be that guy who drowns out everyone else&amp;rsquo;s stream.&lt;/p&gt;

&lt;p&gt;For a filtering example, take &lt;a href="https://plus.google.com/107117483540235115863/posts"&gt;Vic Gundotra&lt;/a&gt;. He&amp;rsquo;s in my &amp;ldquo;following&amp;rdquo; circle because he posts relevant news about google+ itself that I want to be kept up to date on. He also shares photos of him and his wife, and general life news. No offence to Vic, but I don&amp;rsquo;t really care for that other stuff, and to be honest I feel a little invasive looking at pictures of him and his wife. I would very much like to see &lt;em&gt;only&lt;/em&gt; Vic&amp;rsquo;s &amp;ldquo;google-news&amp;rdquo; persona.&lt;/p&gt;

&lt;p&gt;Even if I want to see all of your updates, I don&amp;rsquo;t want to see them in the same place. If I want to catch up on what&amp;rsquo;s going on in the lives of the people closest to me, I don&amp;rsquo;t want to see all of my best friend&amp;rsquo;s links to geek news and neat programming ideas. I still want to read such things, but I&amp;rsquo;d much rather see them in my &amp;ldquo;geeky news&amp;rdquo; stream when I feel like catching up on that sort of thing.&lt;/p&gt;

&lt;h3&gt;Actual implementation&lt;/h3&gt;

&lt;p&gt;I imagine personas would work pretty much like tags do on a blog. You would typically use one or two, and you&amp;rsquo;d typically keep the number quite low. There&amp;rsquo;s a pragmatic issue about what happens when you add new tags, and I think the answer is for new tags to be included by default. If my best friend suddenly starts sharing heaps of neat magic tricks, it&amp;rsquo;s much easier for me to ignore that tag (once) than it would be for me to be constantly checking whether any of my friends had suddenly developed wizardly tendencies.&lt;/p&gt;

&lt;p&gt;In practice, it seems likely there would be a relation between tags and circles. For example, I would typically share my &amp;ldquo;geek links&amp;rdquo; and &amp;ldquo;thoughts on current events&amp;rdquo; with everyone, &amp;ldquo;life updates&amp;rdquo; with friends &amp;amp; acquaintances, and &amp;ldquo;random babblings&amp;rdquo; with just my friends. I don&amp;rsquo;t know whether this link should be explicit (by you assigning correlations in the UI) or heuristic (I&amp;rsquo;ll bet google could make some good circle suggestions based on a set of tags, if your behaviour is fairly consistent). In the common case, it should end up little more effort for the poster than selecting circles currently is.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve been told in the past that my ideas about obsessive categorisation (see: &lt;a href="/dist/0install/irank.xml"&gt;irank&lt;/a&gt;) are really good, but that nobody actually cares enough to put as much effort as I&amp;rsquo;m willing to. So I suspect there are a lot of people who would not be at all enthused by this idea, and the effort and complexity of adding it wouldn&amp;rsquo;t be worth it. I really hope that&amp;rsquo;s not true though, because I&amp;rsquo;d honestly love to see this implemented.&lt;/p&gt;


				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/QMHA00irVgE" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/07/09/personas-the-missing-piece-of-google-relationships.html</feedburner:origLink></entry>
	
		<entry>
			<title>The most annoying chrome bug arrives in firefox</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/p9CkTVwc2z4/the-most-annoying-chrome-bug-arrives-in-firefox.html" />
			<updated>2011-06-27T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/06/27/the-most-annoying-chrome-bug-arrives-in-firefox</id>
			<content type="html">
				&lt;p&gt;Ugh. I loathe the feature of chrome that hides &lt;code&gt;"http://"&lt;/code&gt; from the address bar. You can argue that it makes the address bar less scary, but that doesn&amp;rsquo;t change the fact that it is an incomplete representation of a URL, and after 12 months they &lt;em&gt;still&lt;/em&gt; can&amp;rsquo;t do it right and won&amp;rsquo;t provide an option to disable it.&lt;/p&gt;

&lt;p&gt;When &lt;a href="http://code.google.com/p/chromium/issues/detail?id=41467"&gt;chrome implemented it&lt;/a&gt; the response to user frustration was &amp;ldquo;if something is broken, it is a bug and will be fixed&amp;rdquo;. But I&amp;rsquo;ve encountered &lt;a href="http://code.google.com/p/chromium/issues/detail?id=42940&amp;amp;can=1&amp;amp;q=HTTPStripping&amp;amp;colspec=ID%20Stars%20Pri%20Area%20Feature%20Type%20Status%20Summary%20Modified%20Owner%20Mstone%20OS"&gt;a number&lt;/a&gt; of &lt;a href="http://code.google.com/p/chromium/issues/detail?id=64724"&gt;broken things&lt;/a&gt; that the developers either cannot fix or refuse to fix, so clearly that&amp;rsquo;s not true. Not to mention the unnecessary effort fixing all the bugs they actually did fix (this thing was horribly broken when it first landed). Perhaps firefox will actually make sure it works properly, but I doubt it.&lt;/p&gt;

				
				
					&lt;p&gt;&lt;a href="http://browserfame.com/41/firefox-hide-http-address-bar"&gt;(view link)&lt;/a&gt;&lt;/p&gt;
				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/p9CkTVwc2z4" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/06/27/the-most-annoying-chrome-bug-arrives-in-firefox.html</feedburner:origLink></entry>
	
		<entry>
			<title>Shellshape: A Tiling Window Manager for Gnome Shell</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/WIRxvt5Nyq8/shellshape-a-tiling-window-manager-for-gnome-shell.html" />
			<updated>2011-06-26T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/06/26/shellshape-a-tiling-window-manager-for-gnome-shell</id>
			<content type="html">
				&lt;p&gt;&lt;img src="/shellshape/res/logo-400.png" width="400" height="105" alt="shellshape" class="alpha" /&gt;
Today I released the first version of &lt;a href="/shellshape"&gt;shellshape, a tiling window manager plugin for gnome-shell&lt;/a&gt;. It&amp;rsquo;s definitely pre-alpha software, and currently requires a custom fork of the &lt;code&gt;mutter&lt;/code&gt; window manager. I&amp;rsquo;ve had some trouble getting it running due to awful packaging things (I now know far too much about dynamic linking path resolution on linux), but it should work, at least on Fedora 15. Please give it a go if you use gnome-shell - and if not, there&amp;rsquo;s more information and a demo video at the above link.&lt;/p&gt;

&lt;p&gt;It&amp;rsquo;s got a long way to go - there are certainly bugs, and some features aren&amp;rsquo;t done right yet. But it &lt;em&gt;works&lt;/em&gt;, and that&amp;rsquo;s pretty exciting to me after working towards it on and off for about four months.&lt;/p&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/WIRxvt5Nyq8" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/06/26/shellshape-a-tiling-window-manager-for-gnome-shell.html</feedburner:origLink></entry>
	
		<entry>
			<title>Node.js is backwards</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/1w3l-lfZo1k/node-js-is-backwards.html" />
			<updated>2011-06-24T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/06/24/node-js-is-backwards</id>
			<content type="html">
				

				
				
					&lt;p&gt;&lt;a href="http://blog.ankurgoyal.com/post/6433642218/node-js-is-backwards"&gt;(view link)&lt;/a&gt;&lt;/p&gt;
				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/1w3l-lfZo1k" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/06/24/node-js-is-backwards.html</feedburner:origLink></entry>
	
		<entry>
			<title>daglink: organise your system configuration</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/cHNXLPbsEqA/daglink-organise-your-system-configuration.html" />
			<updated>2011-06-10T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/06/10/daglink-organise-your-system-configuration</id>
			<content type="html">
				&lt;p&gt;I just released &lt;a href="/dist/0install/daglink.xml"&gt;daglink&lt;/a&gt;, a tiny program for managing your system configuration. The readme has most of the information, but as a quick overview &lt;code&gt;daglink&lt;/code&gt; allows you to maintain symbolic links from well-known locations (e.g &lt;code&gt;/etc/apt/sources.list.d/&lt;/code&gt;) into locations of your choosing (mine live in &lt;code&gt;~/dev/app-customisations/&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;But more than just creating symlinks, it allows you to create the appropriate links based on tags of your choosing, for example distro, release and keyboard type (yes, I do actually have multiple of each of those that I frequently use).&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;ve seen others use &lt;code&gt;git&lt;/code&gt; or &lt;code&gt;puppet&lt;/code&gt; for this, and until now I just had a hand-rolled script and some well-named files. So I figured I might as well write something proper. Did I mention it has built-in support for zero install URLs instead of paths, if you&amp;rsquo;re into that sort of thing? I&amp;rsquo;m not sure how useful that is (or should be), but it could turn out useful for some very niche cases.&lt;/p&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/cHNXLPbsEqA" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/06/10/daglink-organise-your-system-configuration.html</feedburner:origLink></entry>
	
		<entry>
			<title>Ruby's unicode treatment</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/ZZ68EphflxM/ruby-s-unicode-treatment.html" />
			<updated>2011-05-05T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/05/05/ruby-s-unicode-treatment</id>
			<content type="html">
				&lt;p&gt;I recently came across &lt;a href="http://yehudakatz.com/2010/05/05/ruby-1-9-encodings-a-primer-and-the-solution-for-rails/comment-page-1/"&gt;this enlightening post&lt;/a&gt; on the changes to strings and encodings in ruby 1.9. As a python lover who has only used ruby 1.8 so far, it&amp;rsquo;s interesting to see the different approaches to very similar problems in python 3 and ruby 1.9.&lt;/p&gt;

&lt;p&gt;I may be biased, but ruby&amp;rsquo;s implementation sounds like it will lead to a lot of pain and bugs, while python&amp;rsquo;s implementation will lead to a little more pain as you are forced to learn about encodings, and a lot less bugs (as you are forced to learn about encodings). Let me explain why:&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2&gt;Ruby conflates the concept of strings and bytes&lt;/h2&gt;

&lt;p&gt;This has been the biggest problem with encodings in most languages for a long time. It saddens me to see that ruby is still not fixing it. In python 3, there are &lt;code&gt;bytes&lt;/code&gt; and there are &lt;code&gt;str&lt;/code&gt;s. Trying to do the wrong thing (without converting one to the other by explicitly &lt;code&gt;encode&lt;/code&gt;ing or &lt;code&gt;decode&lt;/code&gt;ing) will &lt;strong&gt;always&lt;/strong&gt; result in a &lt;code&gt;TypeError&lt;/code&gt;. In ruby, doing the wrong thing will &lt;strong&gt;sometimes&lt;/strong&gt; raise an error.&lt;/p&gt;

&lt;p&gt;Yes, both languages are dynamically typed - but the difference is still important. In python, you will get an error as soon as you run bad code. In ruby, you will get an error as soon as you run bad code &lt;em&gt;with input data that is non-ASCII (and sometimes only if you use multiple encodings)&lt;/em&gt;. And how much of your test data is ASCII? If your native tongue is english, probably most of it. That means your test cases will not catch encoding errors - your users will.&lt;/p&gt;

&lt;p&gt;Note that neither language can prevent bugs that are due to &lt;em&gt;incorrectly&lt;/em&gt; specifying the encoding of a given string. But in python, you have to specify this a lot less often (see my next point) and the conversion is represented at a type level, therefore it should be easier to spot and a more obvious test candidate.&lt;/p&gt;

&lt;p&gt;I liken this approach to weak typing. In perl, 1 is less than 2. And 9 is less than 10. Unless one of your arguments is actually a string, at which point perl silently converts them both to strings. What&amp;rsquo;s worse, you will still think it works while you happen to use values 1 through 9 - only once you reach 10 will perl happily declare &amp;ldquo;10&amp;rdquo; to be less than &amp;ldquo;9&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;Ruby and python are both strongly typed and will not allow you to compare a number to a string&lt;sup id="fnref:weak"&gt;&lt;a href="#fn:weak" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;, because &lt;em&gt;that doesn&amp;rsquo;t make sense&lt;/em&gt;. The same goes with strings and bytes. It&amp;rsquo;s far more confusing since in the most common case (ASCII), they happen to equal the same thing, but combining the two in any operation (without explicit conversion) simply &lt;em&gt;does not make sense&lt;/em&gt;. It may happen to work in a bunch of common cases, but that&amp;rsquo;s not how you write robust software.&lt;/p&gt;

&lt;h2&gt;Ruby makes you think about the encoding of every single string&lt;/h2&gt;

&lt;p&gt;If I read that article correctly, there is no &lt;code&gt;String&lt;/code&gt;-like type in ruby that allows you to arbitrarily concatenate two strings, regardless of their original encoding. Rather the normal concatenation functions will &lt;em&gt;happen&lt;/em&gt; to work&lt;sup id="fnref:happen"&gt;&lt;a href="#fn:happen" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt; if the two strings are of the same encoding, or if one value happens to be only ASCII. If you want to properly concatenate two strings, you either have to:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;check the encoding at each concatenation operation (incredibly cumbersome), or&lt;/li&gt;
  &lt;li&gt;ensure your entire application (or at least the part that you wrote) converts strings to your preferred encoding at every boundary. This includes not only your interfaces to the outside world (HTTP, files on disk) but also potentially any string that you receive from a library.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;And if you&amp;rsquo;re writing a library, you&amp;rsquo;ll have to resort to option (1), since you don&amp;rsquo;t get to control the rest of the application.&lt;/p&gt;

&lt;p&gt;In python, the only times you have to deal with encodings are when going to or from &lt;code&gt;bytes&lt;/code&gt;, which is exactly when you &lt;em&gt;need&lt;/em&gt; to know about encodings. So you still need to specify encodings for network traffic, or data on disk. But once you have a string, you never need to know its encoding, and it will combine just fine with any other string. What&amp;rsquo;s more, you will &lt;em&gt;never&lt;/em&gt; be under the mistaken impression that your data is a string, when in fact it is really just binary data (or at least, you&amp;rsquo;ll find out as soon as you run that code).&lt;/p&gt;

&lt;p&gt;Python libraries that don&amp;rsquo;t need to encode or decode data to or from &lt;code&gt;bytes&lt;/code&gt; simply deal with the unicode &lt;code&gt;str&lt;/code&gt; type, and never have to care about encodings. Whereas it sounds like &lt;code&gt;erb&lt;/code&gt; and other ruby templating libraries will either have to do a lot of encoding checks / conversions, or will only work on strings with the correct encoding.&lt;/p&gt;

&lt;h2&gt;A caveat: perhaps unicode is not sufficient?&lt;/h2&gt;

&lt;p&gt;According to the &lt;a href="http://yehudakatz.com/2010/05/05/ruby-1-9-encodings-a-primer-and-the-solution-for-rails/comment-page-1/"&gt;original post&lt;/a&gt;, ruby cannot use a single unicode type because some encodings (specifically &lt;code&gt;SHIFT-JIS&lt;/code&gt;) cannot be losslessly converted to unicode. This is the first I&amp;rsquo;ve heard of it, and information is scarce on the matter (and the article itself provides no further clues). I did eventually find &lt;a href="http://apps.ycombinator.com/item?id=1322918"&gt;this thread on hacker news&lt;/a&gt;, which suggests the article is referring to &lt;a href="http://en.wikipedia.org/wiki/Han_unification"&gt;Han unification&lt;/a&gt;. I don&amp;rsquo;t know enough about asian character sets to know how big of an issue this actually is, but it&amp;rsquo;s an interesting one (and new to me). It would be a huge shame if unicode were not sufficient to represent some character sets, given that universality was the entire point of the unicode effort. Even so, I&amp;rsquo;m sure there are ways to deal with this situation that don&amp;rsquo;t have the unfortunate effects I&amp;rsquo;ve listed above - there is still no excuse for failing to properly separate &lt;code&gt;Bytes&lt;/code&gt; from &lt;code&gt;String&lt;/code&gt;s, for example.&lt;/p&gt;

&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:weak"&gt;
      &lt;p&gt;Apparently python 2 does not forbid this due to a weird implementation detail (although it at least gives &lt;a href="http://stackoverflow.com/questions/3270680/how-does-python-compare-string-and-int"&gt;less misleading results&lt;/a&gt;; a string is &lt;em&gt;always&lt;/em&gt; greater than an integer). Thankfully python 3 will raise a &lt;code&gt;TypeError&lt;/code&gt;.&lt;a href="#fnref:weak" rev="footnote"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:happen"&gt;
      &lt;p&gt;Note that things which merely &lt;em&gt;happen&lt;/em&gt; to work will almost universally stop doing so in painfully inconvenient (and often confusing) ways&lt;a href="#fnref:happen" rev="footnote"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/ZZ68EphflxM" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/05/05/ruby-s-unicode-treatment.html</feedburner:origLink></entry>
	
		<entry>
			<title>Awesome light drawing video</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/km0ZEyS0FSc/awesome-light-drawing-video.html" />
			<updated>2011-05-05T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/05/05/awesome-light-drawing-video</id>
			<content type="html">
				&lt;p&gt;Courtesy Ned.&lt;/p&gt;

				
				
					&lt;p&gt;&lt;a href="http://www.youtube.com/watch?v=9ZohmoG981s"&gt;(view link)&lt;/a&gt;&lt;/p&gt;
				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/km0ZEyS0FSc" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/05/05/awesome-light-drawing-video.html</feedburner:origLink></entry>
	
		<entry>
			<title>From Ubuntu to Fedora</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/Vj-l43N3Z3I/from-ubuntu-to-fedora.html" />
			<updated>2011-05-03T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/05/03/from-ubuntu-to-fedora</id>
			<content type="html">
				&lt;p&gt;I recently moved from Ubuntu to Fedora. It seemed like the right time for it. I just got a new computer, so I&amp;rsquo;d have to do a fresh install of &lt;em&gt;something&lt;/em&gt; anyway. And on the day that my computer arrived, the Fedora 15 beta was released. Perhaps it was meant to be?&lt;/p&gt;

&lt;!-- more --&gt;

&lt;h2&gt;Table of contents:&lt;/h2&gt;

&lt;ul id="markdown-toc"&gt;
  &lt;li&gt;&lt;a href="#why"&gt;Why switch?&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href="#hack"&gt;To hack&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="#explore"&gt;To see what&amp;rsquo;s out there&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="#control"&gt;Ubuntu is a bit of a control freak&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href="#hows-fedora"&gt;How&amp;rsquo;s Fedora?&lt;/a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href="#package-menegement"&gt;Package management&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="#ppas"&gt;PPAs and private repositories&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="#system-stuff"&gt;Kernels and encryption and security, oh my!&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="#freedom"&gt;Free as in beards&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="#bugs"&gt;Miscellaneous bugs&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="#shell"&gt;The shell&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href="#team"&gt;A Team player&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href="#summary"&gt;Summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;h1 id="why"&gt;Why switch?&lt;/h1&gt;

&lt;p&gt;I have a number of reasons for trying Fedora, but the biggest few are:&lt;/p&gt;

&lt;h3 id="hack"&gt;To hack&lt;/h3&gt;
&lt;p&gt;Most simply, I want to hack on gnome-shell, and Fedora is currently the only distro to include it. It&amp;rsquo;s entirely possible that I&amp;rsquo;ll switch back to Ubuntu in 6 months time, when gnome-shell is supported. But I&amp;rsquo;d rather not put my project on hold until then.&lt;/p&gt;

&lt;h3 id="explore"&gt;To see what&amp;rsquo;s out there&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;d like to see how different distros actually are. Ubuntu was the first linux distro I used at home, and I feel it&amp;rsquo;s worth knowing what things are different / better / worse between distros. I&amp;rsquo;m pretty adept at maintaining my own preferred system configuration, so in theory it should be reasonably painless to switch.&lt;/p&gt;

&lt;h3 id="control"&gt;Ubuntu is a bit of a control freak&lt;/h3&gt;
&lt;p&gt;Ubuntu has a reputation for being heavily patched, which can interfere with submitting upstream bug reports and such. I heaven&amp;rsquo;t really experienced that either way, but many recent changes in natty are Ubuntu-specific patches that I disagree with. It is starting to feel to me like Ubuntu is becoming the HTC of linux - HTC provides great android phones, but they keep sticking their foot in and messing with the software, which in my experience has led to more bugs, slower software and a general muddying of the android experience.&lt;/p&gt;

&lt;p&gt;I have far greater faith in canonical&amp;rsquo;s ability to produce quality software than I do for HTC (and canonical does actually contribute things upstream), but the analogy still holds to some degree. Ubuntu wants to differentiate itself from upstream and other distros, but personally I would prefer a less opinionated distro. I have heard that Fedora is closer to upstream sources, and is governed more by the community and less by Mark Shuttleworth (who I&amp;rsquo;m sure is a great guy, but that doesn&amp;rsquo;t always make him right).&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;So, having some of my reasoning out of the way, let&amp;rsquo;s delve into how it&amp;rsquo;s going so far. Note that this is only a comparison to Ubuntu, not other distros - I haven&amp;rsquo;t actually used anything else (yet).&lt;/p&gt;

&lt;h1 id="hows-fedora"&gt;How&amp;rsquo;s Fedora?&lt;/h1&gt;

&lt;p&gt;Overall, it&amp;rsquo;s pretty nice. I&amp;rsquo;ve had a few issues with system configuration and kernel modules that Ubuntu makes easier, but I&amp;rsquo;ve also had a bunch of bugs disappear and things work better than they did in Ubuntu. I don&amp;rsquo;t think either distro is wildly better than the other, but so far I&amp;rsquo;m personally happier with Fedora.&lt;/p&gt;

&lt;h3 id="package-menegement"&gt;Package management&lt;/h3&gt;
&lt;p&gt;For most users, the biggest difficulty in setting up a new system is simply the package manager, its interface, and actual package names. There&amp;rsquo;s pretty much the same selection of software, it just might have different names. This probably affects developers more than end-users, as most of the different names are for libraries.&lt;/p&gt;

&lt;p&gt;I think I like yum a little better than apt, as it&amp;rsquo;s command line interface seems more clean and logical. But really, they do the same thing and they both manage it just fine. &lt;code&gt;rpm&lt;/code&gt; commands are just as archaic as &lt;code&gt;dpkg&lt;/code&gt; ones, but this &lt;a href="http://nakedape.cc/wiki/PackageManagerCheatsheet"&gt;cheat sheet&lt;/a&gt; covers all I really need for both of them.&lt;/p&gt;

&lt;p&gt;Yum also does a lot more automatic refreshing, which is convenient because you don&amp;rsquo;t have to remember to do it yourself (I&amp;rsquo;ve had some bizarre apt sessions due to stale package data), but can be annoying when you forget the &lt;code&gt;-C&lt;/code&gt; (cache) option for a simple search or info operation that gets blocked by a metadata refresh.&lt;/p&gt;

&lt;p&gt;The Ubuntu software center is a really nice UI, and something that I hope &lt;a href="http://distributions.freedesktop.org/wiki/AppStream"&gt;appstream&lt;/a&gt; will bring to the other distros soon. But the packagekit-based UI in Fedora is more than enough for me. One neat feature is that after installing a package, it will list the user-facing applications that were installed, tell you their menu heirarchy locations, and allow you to run any of them. Much better than hunting in the &amp;ldquo;Applications&amp;rdquo; menu looking for that thing you just installed.&lt;/p&gt;

&lt;p&gt;One of the benefits of Fedora using &lt;a href="http://www.packagekit.org/"&gt;PackageKit&lt;/a&gt; (or maybe it&amp;rsquo;s yum&amp;rsquo;s doing?) is that the package manager isn&amp;rsquo;t so blocking. Operations can still only proceed one at a time (although read-only operations seem to work while other things are happening), but it&amp;rsquo;s not like on Ubuntu where you can&amp;rsquo;t run any apt commands while you have synaptic open.&lt;/p&gt;

&lt;p&gt;One random note, &lt;code&gt;yum info&lt;/code&gt; tells you what repository an installed package comes from. I can&amp;rsquo;t believe I haven&amp;rsquo;t found the apt or dpkg invocation to do the same, but I&amp;rsquo;ve looked, and it shouldn&amp;rsquo;t be that hard.&lt;/p&gt;

&lt;h3 id="ppas"&gt;PPAs and private repositories&lt;/h3&gt;

&lt;p&gt;I believe Fedora has a similar mechanism to launchpad PPAs, although it&amp;rsquo;s not as widely used and possibly not as easy. That doesn&amp;rsquo;t really bother me, as I prefer to use &lt;a href="http://0install.net"&gt;0install&lt;/a&gt; for as many non-distro applications as I can. I could do a whole post about this, but PPAs solve the problem for one step (&amp;ldquo;I have nonstandard software that depends only on standard libraries&amp;rdquo;). It does not solve the problem in general (&amp;ldquo;I have nonstandard software with arbitrary dependencies&amp;rdquo;), nor does it attempt to address the very important issue of &amp;ldquo;I want to use different versions of libraries that system components depend upon&amp;rdquo; (a.k.a &lt;a href="http://en.wikipedia.org/wiki/Dependency_hell"&gt;dependency hell&lt;/a&gt;). It all seems like a lot of effort for a reasonably limited solution. I strongly believe that &lt;a href="http://0install.net"&gt;0install&lt;/a&gt; has it right, so am unlikely to ever embrace PPAs or whatever it is that Fedora has in their place.&lt;/p&gt;

&lt;h3 id="system-stuff"&gt;Kernels and encryption and security, oh my!&lt;/h3&gt;

&lt;p&gt;This is where the Fedora transition was not so smooth. Ubuntu has a neat facility for encrypting your home directory, or a &lt;code&gt;Private&lt;/code&gt; folder within it. It uses ecryptfs, which is available on Fedora, but not default and not really exposed in the UI. I did get it installed, but had &lt;a href="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=590081"&gt;troubles with the kernel modules not being loaded automatically&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="http://en.wikipedia.org/wiki/Security-Enhanced_Linux"&gt;SELinux&lt;/a&gt; is probably a great thing, but I&amp;rsquo;m not sure I&amp;rsquo;ll get much use out of it. It put itself into terrified mode when I tried to run things with my &lt;code&gt;/home&lt;/code&gt; directory copied over from my old Ubuntu disk, as evidently it was lacking important SELinux metadata. But once I found out how to tell SELinux to &lt;a href="http://www.centos.org/docs/5/html/5.2/Deployment_Guide/sec-sel-fsrelabel.html"&gt;relabel my hard drive&lt;/a&gt;, it hasn&amp;rsquo;t made a peep. I&amp;rsquo;m still not sure if I&amp;rsquo;ll get any benefit from it, but it sounds like a good thing to have.&lt;/p&gt;

&lt;p&gt;I also had problems with VirtualBox not having the right kernel modules loaded, although it did work once (I think I upgraded my kernel since). I&amp;rsquo;m running a beta, so this hopefully isn&amp;rsquo;t normal behaviour.&lt;/p&gt;

&lt;p&gt;On a positive system-level note, from everything I have read systemd sounds like a much better boot system than upstart, although I have little experience with either.&lt;/p&gt;

&lt;h3 id="freedom"&gt;Free as in beards&lt;/h3&gt;

&lt;p&gt;Fedora, like debian, doesn&amp;rsquo;t ship any non-free codecs (mp3, h.264, etc) or other patent-encumbered technology (flash) by default. Ubuntu does via a separate repository that can be enabled at install time (or after). This is much nicer for users, although I completely understand and sympathize with the puritan position.&lt;/p&gt;

&lt;p&gt;Of course, I still need the damn codecs, and I need flash. So there is more work in Fedora to get the appropriate repository set up (&lt;a href="http://rpmfusion.org/"&gt;rpm fusion&lt;/a&gt;), and I ended up installing flash manually because of dependency troubles. That&amp;rsquo;s possibly related to the fact I&amp;rsquo;m running a beta.&lt;/p&gt;

&lt;p&gt;Fedora also doesn&amp;rsquo;t package chromium in the default repos, for what sound like &lt;a href="http://ostatic.com/blog/making-projects-easier-to-package-why-chromium-isnt-in-fedora"&gt;pretty sane reasons&lt;/a&gt;. It sounds like google is more to blame than Fedora on that front, but again the user is the one who has to deal with the slight inconvenience of adding a third-party repo.&lt;/p&gt;

&lt;h3 id="bugs"&gt;Miscellaneous bugs&lt;/h3&gt;

&lt;p&gt;These are presumably not common to many users, but gee they annoy me.&lt;/p&gt;

&lt;p&gt;Pros for Fedora:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;gpg-agent actually works out of the box&lt;/li&gt;
  &lt;li&gt;my keyboard&amp;rsquo;s &lt;code&gt;volume_up&lt;/code&gt; key is no longer &lt;a href="https://bugs.launchpad.net/ubuntu/+source/linux/+bug/377175"&gt;irrevocably bound to activate the screensaver&lt;/a&gt;. For 3 Ubuntu releases straight I had to manually cripple the &lt;code&gt;gnome-screensaver&lt;/code&gt; system binary in order to use my keyboard properly.&lt;/li&gt;
  &lt;li&gt;I can change the GVim icon with a theme (it seems to be hard coded into the binary in Ubuntu)&lt;/li&gt;
  &lt;li&gt;Pretty much all the things I mentioned in my &lt;a href="/2011/04/24/natty-ui-fumbles.html"&gt;Natty UI Fumbles post&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons for Fedora:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I can&amp;rsquo;t seem to enable &lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=699628"&gt;rgba subpixel smoothing&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=626248"&gt;Guake crashes on startup&lt;/a&gt;. Probably a general gnome bug.&lt;/li&gt;
  &lt;li&gt;nautilus keeps forgetting my background image, and turning the screen white. I&amp;rsquo;m using a gnome-shell hack to get it to display the desktop, so that could be why ;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Equally broken:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Both unity and gnome-shell fail to raise the window you alt-tab to if you have enabled focus-follows-mouse and your mouse does not happen to already be over the desired window. That is going to annoy me.&lt;/li&gt;
  &lt;li&gt;&lt;a href="https://bugzilla.redhat.com/show_bug.cgi?id=692760"&gt;Suspend resets keyboard layout&lt;/a&gt;. This bug probably exists in Ubuntu, but I could never get my old computer to come back from suspend anyway (probably a hardware / kernel thing).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id="shell"&gt;The shell&lt;/h3&gt;

&lt;p&gt;Oh, the shell.&lt;/p&gt;

&lt;p&gt;This hopefully won&amp;rsquo;t be such a hot topic in 6 months time, but right now it&amp;rsquo;s probably the biggest factor anyone needs to consider when upgrading / installing either of these distros.&lt;/p&gt;

&lt;p&gt;Overall, I much prefer gnome-shell. It seems reasonably well designed and calm (for the most part), whereas my experience with unity made it seem more haphazard. But overall, there seem to be good ideas in both, and I hope that the best ideas from each will eventually make it into the other. Right now I have plans to work on gnome-shell extensions, so there is simply little point in me running an operating system that prevents that.&lt;/p&gt;

&lt;p&gt;Particular notes, while I&amp;rsquo;m on the subject:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;I can&amp;rsquo;t believe gnome-shell doesn&amp;rsquo;t display the contents of your &lt;code&gt;Desktop&lt;/code&gt; folder. You can enable it with gnome-tweak-tool, but it&amp;rsquo;s a terrible default (and it keeps losing my background image).&lt;/li&gt;
  &lt;li&gt;The &lt;a href="http://live.gnome.org/GnomeShell/Design/Whiteboards/SystemStopRestart"&gt;choice to not have an actual &amp;ldquo;shut down&amp;rdquo; option in the session menu&lt;/a&gt; is pure crazy. Easily fixed with an extension, but still a terrible default.&lt;/li&gt;
  &lt;li&gt;Alt-tab seems much better thought out (in combination with alt-`) than unity.&lt;/li&gt;
  &lt;li&gt;Launching multiple apps at once is tedious, because the dock is only visible in overlay mode, and overlay mode disappears whenever you launch an app. So you have to keep tapping the windows key.&lt;/li&gt;
  &lt;li&gt;I didn&amp;rsquo;t think I would, but I actually quite like the automatic workspace management now that I&amp;rsquo;m used to it. I still have trouble if I want to swap two workspaces (If you move everything out of a workspace, it disappears!) but other than that it&amp;rsquo;s treating me well.&lt;/li&gt;
  &lt;li&gt;There&amp;rsquo;s no way for applications to dynamically add things to the top panel. I hope this will change in future releases, but the persistent notification / applet problem in general seems like it has simply been swept under the rug (or hidden in the bottom-right corner ;)) for now.&lt;/li&gt;
  &lt;li&gt;Speaking of issues that have been ignored, I&amp;rsquo;m baffled by the treatment of minimised windows (the button has been removed, but the functionality is still there. They don&amp;rsquo;t go anywhere, and still clog up the overview mode). I don&amp;rsquo;t know if that will change in future releases, but I feel something has to change&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you&amp;rsquo;re new to the shell or don&amp;rsquo;t know how it works, the &lt;a href="http://live.gnome.org/GnomeShell/CheatSheet"&gt;cheat sheet&lt;/a&gt; is a good starting point.&lt;/p&gt;

&lt;p&gt;I still think the gnome shell is a much improved interface over gnome 2, and hopefully it&amp;rsquo;ll keep getting better over the next few releases. Plus, it&amp;rsquo;s bound to be heaps better once I&amp;rsquo;ve added tiling window management to it ;)&lt;/p&gt;

&lt;h3 id="team"&gt;A Team player&lt;/h3&gt;

&lt;p&gt;There&amp;rsquo;s a little bit of a theme in this post. My personal preference is for distributions not to try too hard to differentiate, and rather focus on bug fixing and integration work, as well as improving upstream software rather than forking it. For example, Fedora sticks to gnome 3 and PackageKit, which are both cross-distro initiatives. While Ubuntu has written its own desktop environment (&lt;a href="http://unity.ubuntu.com/"&gt;Unity&lt;/a&gt;) and, still doesn&amp;rsquo;t have a working packagekit UI.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m particularly biased with the packagekit thing because &lt;a href="http://0install.net"&gt;0install&lt;/a&gt; uses it to install dependencies that are only available as system packages (because they have not been ported to 0install). 0install is my absolute favourite piece of software (well, maybe a tie with vim). It&amp;rsquo;s a dependency manager for cross-distro, cross-platform, decentralised applications and libraries. I find it ridiculous that every distro has it&amp;rsquo;s own name for the exact same software, and I have started using tiny 0install feeds to simply abstract over that for the packages that I need to depend on for my own software and scripts. Happily, almost all of the &lt;a href="/dist/0install/index/"&gt;0install feeds I&amp;rsquo;ve published&lt;/a&gt; (90+ at last count!) worked just fine on Fedora without additional effort on my part.&lt;/p&gt;

&lt;h1 id="summary"&gt;Summary&lt;/h1&gt;

&lt;p&gt;Overall, I&amp;rsquo;m currently happier with Fedora then I was with Ubuntu. I&amp;rsquo;ve listed a lot of issues here, but I&amp;rsquo;ve fixed a lot of them (and ubuntu had its fair share). It was definitely a little harder to get set up the way that I want, but that&amp;rsquo;s a one-off effort. And a lot of it is due to very new and very recent decisions (like the shell), which I hope will flatten out in further releases so that users are able to run whatever software they prefer. I&amp;rsquo;m thankful for the work Ubuntu has done to invigorate the linux desktop space, but right now I&amp;rsquo;m enjoying a distro that doesn&amp;rsquo;t feel such a frantic need to differentiate.&lt;/p&gt;


				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/Vj-l43N3Z3I" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/05/03/from-ubuntu-to-fedora.html</feedburner:origLink></entry>
	
		<entry>
			<title>Tip: Transient Notifications in notify-send</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/YO0fDtffaec/tip-transient-notifications-in-notify-send.html" />
			<updated>2011-04-25T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/04/25/tip-transient-notifications-in-notify-send</id>
			<content type="html">
				&lt;p&gt;In gnome-shell (and in contrast to Ubuntu), notifications are persistent by default - they don&amp;rsquo;t go away until you dismiss them.&lt;/p&gt;

&lt;p&gt;I have been using &lt;code&gt;notify-send&lt;/code&gt; for some time to pop up quick messages that do not need to stick around, so I&amp;rsquo;m happy to have found how you can &lt;a href="http://live.gnome.org/GnomeShell/Design/Guidelines/MessageTray/Compatibility"&gt;make individual notifications transient&lt;/a&gt;. If you want to make a transient &lt;code&gt;notify-send&lt;/code&gt; message, you can do the following:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;notify-send --hint=int:transient:1 [standard-arguments ...]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I&amp;rsquo;ve created a &lt;code&gt;notify-send&lt;/code&gt; script in my &lt;code&gt;~/bin&lt;/code&gt; directory that sets this by default, although that depends on you having added &lt;code&gt;~/bin&lt;/code&gt; before &lt;code&gt;/usr/bin&lt;/code&gt; in your &lt;code&gt;$PATH&lt;/code&gt;&lt;/p&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/YO0fDtffaec" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/04/25/tip-transient-notifications-in-notify-send.html</feedburner:origLink></entry>
	
		<entry>
			<title>New GVim Icon</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/QMRwMDuRZco/new-gvim-icon.html" />
			<updated>2011-04-25T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/04/25/new-gvim-icon</id>
			<content type="html">
				&lt;p&gt;&lt;img class="alpha left" width="125" height="60" src="http://www.vim.org/images/vim_editor.gif" /&gt;
The official &lt;a href="http://www.vim.org/images/vim_editor.gif"&gt;gvim icon&lt;/a&gt; (left) is showing its age. The palette seems to be from the days of 256color, there is no anti-aliasing to speak of in many variants, and it&amp;rsquo;s just generally bland. I have found a few more modern variants, most notably the &lt;a href="http://gnome-look.org/content/preview.php?preview=1&amp;amp;id=127006&amp;amp;file1=127006-1.png&amp;amp;file2=&amp;amp;file3=&amp;amp;name=GVim+%2F+Vim+Tango+Icon+Script"&gt;tango version&lt;/a&gt;, but none of them looked terribly great to me.&lt;/p&gt;

&lt;div style="clear:left;"&gt;&lt;/div&gt;
&lt;p&gt;&lt;img class="alpha left" src="/images/vim-logo/vim-logo-128.png" width="128" height="128" /&gt;
So I set out to create a more modern rendering of the classic logo. I exchanged the round serifs for a round diamond, added some psuedo-3d shading, gradients and shadows. All in all I&amp;rsquo;m quite pleased with how it&amp;rsquo;s turned out: &lt;a href="/images/vim-logo/vim-logo-128.png"&gt;128px&lt;/a&gt; / &lt;a href="/images/vim-logo/vim-logo.svg"&gt;svg&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you&amp;rsquo;d like to use this for gvim, you should do something like this&lt;sup id="fnref:instructions"&gt;&lt;a href="#fn:instructions" rel="footnote"&gt;1&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;mkdir -p ~/.icons
cd ~/.icons
wget http://gfxmonk.net/misc/gvim-icon-gfxmonk.tgz
tar zxf gvim-icon-gfxmonk.tgz
rm gvim-icon-gfxmonk.tgz
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then go to your system&amp;rsquo;s theme selector and pick the &amp;ldquo;gfxmonk&amp;rdquo; icon theme.&lt;/p&gt;

&lt;p&gt;If all the &lt;em&gt;other&lt;/em&gt; (non-gvim) icons have now reverted to the system default and you didn&amp;rsquo;t want that, you will need to edit &lt;code&gt;~/.icons/gfxmonk/index.theme&lt;/code&gt; and set the &lt;code&gt;inherits&lt;/code&gt; value to the name of your preferred icon set&lt;sup id="fnref:painful"&gt;&lt;a href="#fn:painful" rel="footnote"&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note&lt;/em&gt;: the svg icon may need the &lt;code&gt;norasi&lt;/code&gt; font installed to display properly.&lt;/p&gt;

&lt;div class="footnotes"&gt;
  &lt;ol&gt;
    &lt;li id="fn:instructions"&gt;
      &lt;p&gt;These instructions have been tested to work on fedora, but I fear other distros may have wildly different mechanisms for overriding icons.&lt;a href="#fnref:instructions" rev="footnote"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id="fn:painful"&gt;
      &lt;p&gt;Forgive me if there is a better way for packaging/installing icons, this is my first attempt.&lt;a href="#fnref:painful" rev="footnote"&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;

				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/QMRwMDuRZco" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/04/25/new-gvim-icon.html</feedburner:origLink></entry>
	
		<entry>
			<title>Natty UI Fumbles</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/FaB9G50Z-SY/natty-ui-fumbles.html" />
			<updated>2011-04-24T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/04/24/natty-ui-fumbles</id>
			<content type="html">
				&lt;p&gt;While my main computer is out of action, I&amp;rsquo;ve been trying beta 2 of ubuntu 11.04 (Natty Narwhal). The biggest change in this version is the introduction of &lt;a href="http://unity.ubuntu.com/"&gt;unity&lt;/a&gt;, but there are also a number of other UI changes. Here are some of the bad bits:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The new scrollbars break a few interactions that I am rather fond of:
    &lt;ul&gt;
      &lt;li&gt;Sometimes the grabber is inside the window, sometimes it&amp;rsquo;s outside.&lt;/li&gt;
      &lt;li&gt;If you scroll up or down by pressing the buttons a few times, and then pause to read, and then try to click the arrow again, it may have disappeared - leading to awfully surprising results.&lt;/li&gt;
      &lt;li&gt;You can&amp;rsquo;t use the neat trick of middle-clicking anywhere in the scrollbar pane to immediately bring the scrubber there (instead you have to find its current location, then drag it to where you want it to be).&lt;/li&gt;
      &lt;li&gt;If the orange scrubber is taller than the pair of arrows and you want to hit one of the arrows, it remains a moving target until you actually leave the window&amp;rsquo;s boundary.&lt;/li&gt;
      &lt;li&gt;After scrolling with the mouse wheel, the orange scrubber turns practically invisible, making it impossible to tell how much scrolling remains.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;The new terminal theme makes it really hard to tell which tab is active.&lt;/li&gt;
  &lt;li&gt;Whenever I press alt (for example, when starting alt-tab or another keyboard shortcut) I get really distracted by the global menu flashing in and out of my peripheral vision.&lt;/li&gt;
  &lt;li&gt;Alt-tab raises windows but does not focus them (&lt;a href="https://bugs.launchpad.net/ubuntu/+source/compiz/+bug/755156"&gt;bug&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Focus-follows-mouse (my preferred setting) is incompatible with the new global menu. &lt;a href="http://askubuntu.com/questions/10481/does-unity-support-disabling-the-global-application-menu"&gt;You can remove the global menu&lt;/a&gt;, but that didn&amp;rsquo;t work for me. For now, I&amp;rsquo;m having to get used to pressing &lt;code&gt;F10&lt;/code&gt;. There&amp;rsquo;s a &lt;a href="https://wiki.ubuntu.com/MenuBar#focus-follows-mouse"&gt;proposal&lt;/a&gt; to fix the global menu behaviour when using focus-follows-mouse, but nobody seems interested in implementing it.&lt;/li&gt;
  &lt;li&gt;There&amp;rsquo;s no way to make &amp;ldquo;fullscreen&amp;rdquo; mean &amp;ldquo;everything but the dock&amp;rdquo;, as it does by default for other non-auto-hide docks. I do like the combination of titlebar &amp;amp; top-bar though.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Given my progress on a tiling window manager for gnome-shell (more on that when it&amp;rsquo;s working, I hope), I may well end up switching to gnome-shell soon. I&amp;rsquo;ll probably try out fedora 15 in the process, I wonder how much of ubuntu I&amp;rsquo;ll miss.&lt;/p&gt;


				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/FaB9G50Z-SY" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/04/24/natty-ui-fumbles.html</feedburner:origLink></entry>
	
		<entry>
			<title>Arrows and Haskell</title>
			<link href="http://feedproxy.google.com/~r/gfxmonk/~3/8PuxwOTTIb8/arrows-and-haskell.html" />
			<updated>2011-04-23T00:00:00+10:00</updated>
			<id>http://gfxmonk.net/2011/04/23/arrows-and-haskell</id>
			<content type="html">
				&lt;p&gt;For a little while I&amp;rsquo;ve been wondering what exactly &lt;code&gt;arrows&lt;/code&gt; were and what they&amp;rsquo;re used for - ever since I came across their syntax in &lt;a href="xmonad.hs"&gt;my window manager&amp;rsquo;s somewhat-indecipherable configuration file&lt;/a&gt; (which I don&amp;rsquo;t claim to understand).&lt;/p&gt;

&lt;p&gt;So anyway, &lt;a href="http://en.wikibooks.org/wiki/Haskell/Understanding_arrows"&gt;this article&lt;/a&gt; is probably the best thing I&amp;rsquo;ve found on the subject. I&amp;rsquo;m still not entirely sure what I&amp;rsquo;d use them for (the parser example that everyone seems to give is a little abstract for my likes), but this article was the easiest introduction to arrows that I&amp;rsquo;ve found, and now I think I finally &lt;em&gt;get&lt;/em&gt; what they are, at least&amp;hellip;&lt;/p&gt;


				
			&lt;img src="http://feeds.feedburner.com/~r/gfxmonk/~4/8PuxwOTTIb8" height="1" width="1"/&gt;</content>
		<feedburner:origLink>http://gfxmonk.net/2011/04/23/arrows-and-haskell.html</feedburner:origLink></entry>
	
 
</feed>

