<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>2718.us blog</title>
	<atom:link href="http://2718.us/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://2718.us/blog</link>
	<description>Miscellaneous Technological Geekery</description>
	<lastBuildDate>Tue, 18 May 2010 02:42:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>MacWJ: It&#8217;s like Windows Journal for Tablet Macs</title>
		<link>http://2718.us/blog/2010/05/07/macwj-its-like-windows-journal-for-tablet-macs/</link>
		<comments>http://2718.us/blog/2010/05/07/macwj-its-like-windows-journal-for-tablet-macs/#comments</comments>
		<pubDate>Fri, 07 May 2010 09:59:44 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[journal]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mac os x]]></category>
		<category><![CDATA[mac osx]]></category>
		<category><![CDATA[macwj]]></category>
		<category><![CDATA[mit]]></category>
		<category><![CDATA[mit license]]></category>
		<category><![CDATA[modbook]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[tablet]]></category>
		<category><![CDATA[tablet pc]]></category>
		<category><![CDATA[windows journal]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=263</guid>
		<description><![CDATA[&#8230; because there are oh-so-many tablet Macs.  There are ModBooks and there are non-Apple tablet machines running Mac OS X.  So, if you have such a device and are looking for something that provides a surface on which to draw, write, etc., with various &#8220;pens&#8221; and with the ability to save to PDF and PNG, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://bitbucket.org/ilg/macwj/"><img class="alignright" title="MacWJ Icon" src="http://bytebucket.org/ilg/macwj/wiki/MacWJ.png" alt="MacWJ" style="border:0;" width="256" height="256" /></a>&#8230; because there are oh-so-many tablet Macs.  There are <a href="http://www.axiotron.com/index.php?id=modbook">ModBooks</a> and there are non-Apple tablet machines running Mac OS X.  So, if you have such a device and are looking for something that provides a surface on which to draw, write, etc., with various &#8220;pens&#8221; and with the ability to save to PDF and PNG, <a href="http://bitbucket.org/ilg/macwj/">MacWJ</a> may be of use to you.  It&#8217;s open-source under MIT license.</p>
<p>MacWJ requires OS X 10.5 or newer and some sort of tablet-pen input, whether a tablet-form computer or a Wacom graphics tablet or something else of that sort.  Ready-to-run recent build(s) are <a href="http://bitbucket.org/ilg/macwj/downloads">available on bitbucket</a>, as well as <a href="http://bitbucket.org/ilg/macwj/src">the full source code</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/05/07/macwj-its-like-windows-journal-for-tablet-macs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simplifying the Assembly of Localizations in Xcode</title>
		<link>http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/</link>
		<comments>http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/#comments</comments>
		<pubDate>Thu, 22 Apr 2010 20:11:51 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[build script]]></category>
		<category><![CDATA[internationalization]]></category>
		<category><![CDATA[localization]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[nib]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[run script]]></category>
		<category><![CDATA[script]]></category>
		<category><![CDATA[sh]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[shell script]]></category>
		<category><![CDATA[target]]></category>
		<category><![CDATA[xcode]]></category>
		<category><![CDATA[xib]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=254</guid>
		<description><![CDATA[A comment on a bitbucket fork of Murky led me to &#8220;Automatically localize your nibs when building&#8220;, which suggests a great way to automate the hard developer-side stuff in localizing in Xcode&#8211;pulling the original strings from the XIB files and putting the translated strings back in.  You absolutely should read the original blog post there, [...]]]></description>
			<content:encoded><![CDATA[<p>A comment on <a href="https://bitbucket.org/philippec/murky">a bitbucket fork</a> of <a href="http://bitbucket.org/snej/murky/wiki/Home">Murky</a> led me to &#8220;<a href="http://developer.casgrain.com/?p=94">Automatically localize your nibs when building</a>&#8220;, which suggests a great way to automate the hard developer-side stuff in localizing in Xcode&#8211;pulling the original strings from the XIB files and putting the translated strings back in.  You absolutely should read the original blog post there, because I cannot adequately explain the big-picture part of the idea with a short quote.</p>
<p>My one complaint with the setup described is that the script for the &#8220;Run Script&#8221; build phase described there is a maintenance headache that I could do without.  Here&#8217;s my solution:  Create two new build targets, both of the &#8220;Shell Script&#8221; type&#8211;these are targets that just run a shell script, so they are created with only a &#8220;Run Script&#8221; build phase.  I called my two new targets &#8220;Create/Update English .strings files&#8221; and &#8220;Create/Update l10n XIBs&#8221; but you can call them whatever you want.</p>
<p>In the &#8220;Create/Update English .strings files&#8221; target&#8217;s &#8220;Run Script&#8221; phase, the script is:</p>
<div class="geshi no bash">
<div class="head"># Create/Update English .strings files</div>
<ol>
<li class="li1">
<div class="de1"><span class="kw1">for</span> xibFile <span class="kw1">in</span> <span class="st0">&quot;$PROJECT_DIR/English.lproj/&quot;</span><span class="sy0">*</span>.xib; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;ibtool &#8211;generate-strings-<span class="kw2">file</span> <span class="st0">&quot;${xibFile}.strings&quot;</span> <span class="st0">&quot;$xibFile&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">done</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">exit</span> <span class="nu0">0</span></div>
</li>
</ol>
</div>
<p>This uses <code>ibtool</code> to create a strings file for every XIB in the English localization (from <code>foo.xib</code>, <code>foo.xib.strings</code> will be created).</p>
<p>In the &#8220;Create/Update l10n XIBs&#8221; target&#8217;s &#8220;Run Script&#8221; phase, the script is:</p>
<div class="geshi no bash">
<div class="head"># Create/Update l10n XIBs</div>
<ol>
<li class="li1">
<div class="de1"><span class="re2">originalResourceDirectory=</span><span class="st0">&quot;$PROJECT_DIR/English.lproj&quot;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">for</span> localizedDirectory <span class="kw1">in</span> <span class="st0">&quot;$PROJECT_DIR/&quot;</span><span class="sy0">*</span>.lproj; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="kw1">if</span> <span class="br0">&#91;</span> localizedDirectory <span class="sy0">!</span>= originalResourceDirectory <span class="br0">&#93;</span>; <span class="kw1">then</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">for</span> xibFile <span class="kw1">in</span> <span class="st0">&quot;${originalResourceDirectory}/&quot;</span><span class="sy0">*</span>.xib; <span class="kw1">do</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;<span class="re2">xibBaseName=</span>$<span class="br0">&#40;</span><span class="kw2">basename</span> <span class="st0">&quot;${xibFile}&quot;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp;ibtool &#8211;strings-<span class="kw2">file</span> <span class="st0">&quot;${localizedDirectory}/${xibBaseName}.strings&quot;</span> \</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &#8211;<span class="kw2">write</span> <span class="st0">&quot;${localizedDirectory}/${xibBaseName}&quot;</span> \</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; <span class="st0">&quot;$xibFile&quot;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">done</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;<span class="kw1">fi</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">done</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw3">exit</span> <span class="nu0">0</span></div>
</li>
</ol>
</div>
<p>This goes through every <code>.lproj</code> directory except <code>English.lproj</code> and uses <code>ibtool</code> to apply the <code>.xib.strings</code> files in those localizations to the XIB files in <code>English.lproj</code>.</p>
<p>By having these as two separate targets, they aren&#8217;t run every time I build and each part can be run on its own, on demand.  By using the power of shell scripting, I avoid having to alter the scripts for every new localization or XIB.</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/04/22/simplifying-the-assembly-of-localizations-in-xcode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Changing from BSD to MIT License</title>
		<link>http://2718.us/blog/2010/03/29/changing-from-bsd-to-mit-license/</link>
		<comments>http://2718.us/blog/2010/03/29/changing-from-bsd-to-mit-license/#comments</comments>
		<pubDate>Mon, 29 Mar 2010 13:56:43 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[bsd]]></category>
		<category><![CDATA[bsd license]]></category>
		<category><![CDATA[google code]]></category>
		<category><![CDATA[license]]></category>
		<category><![CDATA[mit]]></category>
		<category><![CDATA[mit license]]></category>
		<category><![CDATA[new bsd]]></category>
		<category><![CDATA[new bsd license]]></category>
		<category><![CDATA[open source]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=246</guid>
		<description><![CDATA[I&#8217;m changing the license on most (maybe all) of my active open-source projects, largely because the MIT license does not have as many blanks that have to be filled in as the New BSD license and the language is a bit simpler.  To the best of my knowledge, any rights granted under the New BSD [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m changing the license on most (maybe all) of my active open-source projects, largely because the MIT license does not have as many blanks that have to be filled in as the New BSD license and the language is a bit simpler.  To the best of my knowledge, any rights granted under the New BSD license are also granted under the MIT license, so this is really more of a housekeeping/paperwork issue than a conceptual or substantive change.</p>
<p>If this is of concern for some reason, for the things that were under BSD license and no longer are, the version-controlled repositories still have older versions that are BSD-licensed.</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/03/29/changing-from-bsd-to-mit-license/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Integrating Version Control Revisions in Mac App Version Numbers</title>
		<link>http://2718.us/blog/2010/03/22/integrating-version-control-revisions-in-mac-app-version-numbers/</link>
		<comments>http://2718.us/blog/2010/03/22/integrating-version-control-revisions-in-mac-app-version-numbers/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 13:57:26 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[build script]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[version control]]></category>
		<category><![CDATA[version number]]></category>
		<category><![CDATA[version numbering]]></category>
		<category><![CDATA[xcode]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=238</guid>
		<description><![CDATA[When I was using Subversion for version control in working on my Mac apps in Xcode, I had come to use a build script phase to tack on the subversion revision number as the last part to the version number: # tack the subversion revision number onto the CFBundleVersion REV=`svnversion -n &#34;${PROJECT_DIR}&#34;` REV=$&#123;REV/#[0-9]*:/} REV=$&#123;REV//&#91;^0-9&#93;/&#125; BASE=`/usr/libexec/PlistBuddy [...]]]></description>
			<content:encoded><![CDATA[<p>When I was using Subversion for version control in working on my Mac apps in Xcode, I had come to use a build script phase to tack on the subversion revision number as the last part to the version number:</p>
<div class="geshi no bash">
<div class="head"># tack the subversion revision number onto the CFBundleVersion</div>
<ol>
<li class="li1">
<div class="de1"><span class="re2">REV=</span>`svnversion -n <span class="st0">&quot;${PROJECT_DIR}&quot;</span>`</div>
</li>
<li class="li1">
<div class="de1"><span class="re2">REV=</span>$<span class="br0">&#123;</span>REV<span class="sy0">/</span><span class="co0">#[0-9]*:/}</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re2">REV=</span>$<span class="br0">&#123;</span>REV<span class="sy0">//</span><span class="br0">&#91;</span>^<span class="nu0">0</span><span class="nu0">-9</span><span class="br0">&#93;</span><span class="sy0">/</span><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re2">BASE=</span>`<span class="sy0">/</span>usr<span class="sy0">/</span>libexec<span class="sy0">/</span>PlistBuddy -c <span class="st0">&quot;Print :CFBundleVersion&quot;</span> <span class="st0">&quot;${PROJECT_DIR}/Info.plist&quot;</span>`</div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">/</span>usr<span class="sy0">/</span>libexec<span class="sy0">/</span>PlistBuddy -c <span class="st0">&quot;Set :CFBundleVersion $BASE.$REV&quot;</span> <span class="st0">&quot;${TARGET_BUILD_DIR}/${INFOPLIST_PATH}&quot;</span></div>
</li>
</ol>
</div>
<p>This takes the CFBundleVersion from the project&#8217;s Info.plist, adds a period and the subversion revision number, and injects that into the Info.plist of the built product.</p>
<p>When I made the move to Mercurial, I couldn&#8217;t quite do this anymore.  While subversion revision numbers are <a href="http://mathworld.wolfram.com/MonotoneIncreasing.html">monotone increasing</a> and consistent everywhere (they are the unique identifiers of a particular version), Mercurial&#8217;s &#8220;revision numbers&#8221; are local to a particular instance of the repository and may not match up from one instance to another.  Mercurial uses a hash as the unique identifier of a particular version, and these hexadecimal hashes are not monotone, making them unsuitable for use in CFBundleVersion.</p>
<p>Though it took some time, I&#8217;ve finally come to a system with Mercurial that I think is workable:</p>
<div class="geshi no bash">
<div class="head"># use the number of minutes between the tip and the most recent tagged commit</div>
<ol>
<li class="li1">
<div class="de1"><span class="re2">HG_LAST_TAG_TIMESTAMP=</span>$<span class="br0">&#40;</span><span class="sy0">/</span>usr<span class="sy0">/</span><span class="kw3">local</span><span class="sy0">/</span>bin<span class="sy0">/</span>hg log -r <span class="st0">&quot;$(/usr/local/bin/hg log -r &#39;.&#39; &#8211;template &#39;{latesttag}&#39; &#8211;repository &quot;</span><span class="re0">$<span class="br0">&#123;</span>PROJECT_DIR<span class="br0">&#125;</span><span class="sy0">|</span>><span class="st0">&quot;)&quot;</span> &#8211;template <span class="st0">&quot;{date|hgdate}<span class="es0">\n</span>&quot;</span> &#8211;repository <span class="st0">&quot;${PROJECT_DIR}&quot;</span> <span class="sy0">|</span> <span class="kw2">cut</span> -f1 -d<span class="st0">&#39; &#39;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re2">HG_TIP_TIMESTAMP=</span>$<span class="br0">&#40;</span><span class="sy0">/</span>usr<span class="sy0">/</span><span class="kw3">local</span><span class="sy0">/</span>bin<span class="sy0">/</span>hg log -r <span class="st0">&#39;.&#39;</span> &#8211;template <span class="st0">&quot;{date|hgdate}<span class="es0">\n</span>&quot;</span> &#8211;repository <span class="st0">&quot;${PROJECT_DIR}&quot;</span> <span class="sy0">|</span> <span class="kw2">cut</span> -f1 -d<span class="st0">&#39; &#39;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re2">REV=</span>$<span class="br0">&#40;</span><span class="br0">&#40;</span> <span class="br0">&#40;</span><span class="re1">$HG_TIP_TIMESTAMP</span> &#8211; <span class="re1">$HG_LAST_TAG_TIMESTAMP</span><span class="br0">&#41;</span> <span class="sy0">/</span> <span class="nu0">60</span> <span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re2">BASE=</span>`<span class="sy0">/</span>usr<span class="sy0">/</span>libexec<span class="sy0">/</span>PlistBuddy -c <span class="st0">&quot;Print :CFBundleVersion&quot;</span> <span class="st0">&quot;${PROJECT_DIR}/Info.plist&quot;</span>`</div>
</li>
<li class="li1">
<div class="de1"><span class="sy0">/</span>usr<span class="sy0">/</span>libexec<span class="sy0">/</span>PlistBuddy -c <span class="st0">&quot;Set :CFBundleVersion $BASE.$REV&quot;</span> <span class="st0">&quot;${TARGET_BUILD_DIR}/${INFOPLIST_PATH}&quot;</span></div>
</li>
</ol>
</div>
<p>This calculates the number of minutes between the most recent tagged ancestor of the tip and the tip itself and adds that to the CFBundleVersion.  Because it&#8217;s time-based, it is guaranteed to be monotone increasing, consistent, and unique (well, provided multiple commits don&#8217;t happen within a 1-minute span, which is safe for me).</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/03/22/integrating-version-control-revisions-in-mac-app-version-numbers/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Converting a Google Code Project from Subversion to Mercurial</title>
		<link>http://2718.us/blog/2010/03/21/converting-a-google-code-project-from-subversion-to-mercurial/</link>
		<comments>http://2718.us/blog/2010/03/21/converting-a-google-code-project-from-subversion-to-mercurial/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 15:01:33 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[convertsvntohg]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[google code]]></category>
		<category><![CDATA[googlecode]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[svnsync]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=234</guid>
		<description><![CDATA[The Google Code support wiki article ConvertingSvnToHg is quite easy to follow, but there is one thing worth noting that is kind of buried in the comments.  Assuming you&#8217;re doing full history conversion, it is very useful to know that running hg convert locally is much much faster than running it on a remote SVN [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://code.google.com/p/support/wiki/ConvertingSvnToHg">Google Code support wiki article ConvertingSvnToHg</a> is quite easy to follow, but there is one thing worth noting that is kind of buried in the comments.  Assuming you&#8217;re doing full history conversion, it is very useful to know that running <code>hg convert</code> locally is much <strong>much</strong> faster than running it on a remote SVN repository, so it is well worth using <code>svnsync</code> to make a local mirror of the SVN repository and then run <code>hg convert</code> on that.</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/03/21/converting-a-google-code-project-from-subversion-to-mercurial/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Subversions is (on its way) Out, Mercurial is In</title>
		<link>http://2718.us/blog/2010/03/20/subversions-is-on-its-way-out-mercurial-is-in/</link>
		<comments>http://2718.us/blog/2010/03/20/subversions-is-on-its-way-out-mercurial-is-in/#comments</comments>
		<pubDate>Sat, 20 Mar 2010 14:33:24 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[distributed version control system]]></category>
		<category><![CDATA[dvcs]]></category>
		<category><![CDATA[hg]]></category>
		<category><![CDATA[mercurial]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[svn]]></category>
		<category><![CDATA[vcs]]></category>
		<category><![CDATA[version control]]></category>
		<category><![CDATA[version control system]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=232</guid>
		<description><![CDATA[I have very happily been using Subversion since 2008.  I was quite clearly late to the version control system (VCS) party and I wish I&#8217;d known about VCS much earlier.  About 5-6 months ago, I finally gave in and tried Mercurial and hated it.  While I could kind of get my head around why I [...]]]></description>
			<content:encoded><![CDATA[<p>I have very happily been using <a href="http://2718.us/blog/tag/subversion/">Subversion</a> since 2008.  I was quite clearly late to the version control system (VCS) party and I wish I&#8217;d known about VCS much earlier.  About 5-6 months ago, I finally gave in and tried <a href="http://mercurial.selenic.com/">Mercurial</a> and hated it.  While I could kind of get my head around why I should like a distributed VCS (DVCS), I just couldn&#8217;t make the paradigm work for me.  I was pretty sure that with all the people talking about how great DVCS was, I must be doing something wrong, but that didn&#8217;t stop me from putting Mercurial back on the shelf.</p>
<p>A little over a month ago, I went back and played with Mercurial some more, and it just clicked.  I think it had something to do with reading the <a href="http://mercurial.selenic.com/guide/">Mercurial guide</a>, but I couldn&#8217;t really put my finger on it.  That is, until a few days ago, when I read <a href="http://www.joelonsoftware.com/items/2010/03/17.html">Distributed Version Control is here to stay, baby</a>.  Joel&#8217;s explanation of his transition to DVCS really hit on the shift in thinking that took place for me in moving to Mercurial.  Plus, it has one of the best lines I&#8217;ve ever read in a blog post:</p>
<div>
<blockquote><p>If you are using Subversion, stop it. Just stop. Subversion = Leeches. Mercurial and Git = Antibiotics. We have better technology now.</p></blockquote>
</div>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/03/20/subversions-is-on-its-way-out-mercurial-is-in/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A WebView Subclass with Isolated Cookie Storage</title>
		<link>http://2718.us/blog/2010/03/11/a-webview-subclass-with-isolated-cookie-storage/</link>
		<comments>http://2718.us/blog/2010/03/11/a-webview-subclass-with-isolated-cookie-storage/#comments</comments>
		<pubDate>Thu, 11 Mar 2010 07:38:14 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[cookie]]></category>
		<category><![CDATA[cookies]]></category>
		<category><![CDATA[IGIsolatedCookieWebView]]></category>
		<category><![CDATA[isolated cookies]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mac os x]]></category>
		<category><![CDATA[mit]]></category>
		<category><![CDATA[mit license]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[stackoverflow]]></category>
		<category><![CDATA[subclass]]></category>
		<category><![CDATA[webkit]]></category>
		<category><![CDATA[WebView]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=227</guid>
		<description><![CDATA[Following the advice of Kevin Ballard on StackOverflow, I created IGIsolatedCookieWebView, a subclass of WebView that does not access or affect the system-wide shared cookie storage (shared among all WebKit apps).  Each instance of IGIsolatedCookieWebView has its own cookie storage so that, for example, multiple instances of IGIsolatedCookieWebView within the same application can be logged in [...]]]></description>
			<content:encoded><![CDATA[<p>Following <a href="http://stackoverflow.com/questions/364219/how-can-i-have-multiple-instances-of-webkit-without-sharing-cookies/365080#365080">the advice of Kevin Ballard on StackOverflow</a>, I created <a href="/cocoa/#IGIsolatedCookieWebView">IGIsolatedCookieWebView</a>, a subclass of WebView that does not access or affect the system-wide shared cookie storage (shared among all WebKit apps).  Each instance of IGIsolatedCookieWebView has its own cookie storage so that, for example, multiple instances of IGIsolatedCookieWebView within the same application can be logged in to the same web site with different credentials.  IGIsolatedCookieWebView should be usable in place of WebView, except that IGIsolatedCookieWebView uses the resource load delegate, so that can&#8217;t be used by the application.  IGIsolatedCookieWebView is published under <del datetime="2010-03-29T13:57:00+00:00">a 3-clause BSD</del> an MIT license.</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/03/11/a-webview-subclass-with-isolated-cookie-storage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Drag-Resizable Subclass of NSComboBox</title>
		<link>http://2718.us/blog/2010/03/10/a-drag-resizable-subclass-of-nscombobox/</link>
		<comments>http://2718.us/blog/2010/03/10/a-drag-resizable-subclass-of-nscombobox/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 09:57:02 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[Mac OS X]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[combo box]]></category>
		<category><![CDATA[combobox]]></category>
		<category><![CDATA[drag]]></category>
		<category><![CDATA[drag-resizable]]></category>
		<category><![CDATA[IGResizableComboBox]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[mac os x]]></category>
		<category><![CDATA[mit]]></category>
		<category><![CDATA[mit license]]></category>
		<category><![CDATA[nscombobox]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[resizable]]></category>
		<category><![CDATA[resizable combo box]]></category>
		<category><![CDATA[resizable combobox]]></category>
		<category><![CDATA[subclass]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=223</guid>
		<description><![CDATA[IGResizableComboBox is a drag-resizable subclass of NSComboBox—that is, IGResizableComboBox should be usable in place of NSComboBox and it adds a small bar at the bottom of the pop-up list that can be dragged to resize the pop-up list.  IGResizableComboBox is published under a 3-clause BSD an MIT license. It still has some quirks: behavior is [...]]]></description>
			<content:encoded><![CDATA[<p><a href="/cocoa/#IGResizableComboBox">IGResizableComboBox</a> is a drag-resizable subclass of NSComboBox—that is, IGResizableComboBox should be usable in place of NSComboBox and it adds a small bar at the bottom of the pop-up list that can be dragged to resize the pop-up list.  IGResizableComboBox is published under <del datetime="2010-03-29T13:57:01+00:00">a 3-clause BSD</del> an MIT license.</p>
<p>It still has some quirks:</p>
<ul>
<li><del datetime="2010-03-17T15:31:40+00:00">behavior is strange when the pop-up is above the combo box (whereas it is usually below)</del> [fixed; when the pop-up is above the combo box, the drag-handle is at the top and the top edge moves while the bottom edge stays fixed at the combo box]</li>
<li><del datetime="2010-03-10T22:37:05+00:00">the formula for resetting the number of visible items after dragging occurs is not quite right</del> [fixed; dragging now snaps to whole-item positions]</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/03/10/a-drag-resizable-subclass-of-nscombobox/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Randomizing by Random-Comparison Sorting (Revisited)</title>
		<link>http://2718.us/blog/2010/02/24/randomizing-by-random-comparison-sorting-revisited/</link>
		<comments>http://2718.us/blog/2010/02/24/randomizing-by-random-comparison-sorting-revisited/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 21:09:28 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[algorithms]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[browser ballot]]></category>
		<category><![CDATA[bubblesort]]></category>
		<category><![CDATA[eu]]></category>
		<category><![CDATA[european union]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[mathematica]]></category>
		<category><![CDATA[mathematics]]></category>
		<category><![CDATA[mergesort]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[nb]]></category>
		<category><![CDATA[quicksort]]></category>
		<category><![CDATA[selectionsort]]></category>
		<category><![CDATA[sort]]></category>
		<category><![CDATA[sorting]]></category>
		<category><![CDATA[sorting algorithms]]></category>
		<category><![CDATA[statistics]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=215</guid>
		<description><![CDATA[Yesterday, I posted the results of my quick exploration of whether sorting the list {0,1,2,3,4} using a comparison function that randomly returns &#60; or &#62; (with equal probability).  My exploration was prompted by a report on the non-uniformity of the distribution of the random orderings of the browsers in Microsoft&#8217;s EU browser ballot.  I had [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday, I posted <a href="http://2718.us/blog/2010/02/23/the-eu-browser-ballot-and-random-sorting/">the results of my quick exploration</a> of whether sorting the list {0,1,2,3,4} using a comparison function that randomly returns &lt; or &gt; (with equal probability).  My exploration was prompted by <a href="http://techcrunch.com/2010/02/22/microsoft-ballot-screen/">a report on the non-uniformity of the distribution</a> of the random orderings of the browsers in <a href="http://www.browserchoice.eu/BrowserChoice/browserchoice_en.htm">Microsoft&#8217;s EU browser ballot</a>.  I had said that it seemed likely that the distribution would vary based on the sorting algorithm used.</p>
<p>Today, I have data (and code) that confirms the distribution is sorting-algorithm-dependent.  For each sorting algorithm, 1,000,000 instances of the list {0,1,2,3,4} were sorted with a random comparison function and the relative frequencies (rounded to the nearest whole percent) of each number in each position were computed.<span id="more-215"></span></p>
<table border="1" cellspacing="0">
<tbody>
<tr>
<td>Mathematica&#8217;s Sort[]</td>
<td>
<table>
<tbody>
<tr>
<td>position/number</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>first</td>
<td>18%</td>
<td>12%</td>
<td>12%</td>
<td>12%</td>
<td>46%</td>
</tr>
<tr>
<td>second</td>
<td>18%</td>
<td>24%</td>
<td>18%</td>
<td>18%</td>
<td>24%</td>
</tr>
<tr>
<td>third</td>
<td>20%</td>
<td>20%</td>
<td>26%</td>
<td>20%</td>
<td>12%</td>
</tr>
<tr>
<td>fourth</td>
<td>22%</td>
<td>22%</td>
<td>22%</td>
<td>28%</td>
<td>6%</td>
</tr>
<tr>
<td>fifth</td>
<td>22%</td>
<td>22%</td>
<td>22%</td>
<td>22%</td>
<td>12%</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>BubbleSort</td>
<td>
<table>
<tbody>
<tr>
<td>position/number</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>first</td>
<td>36%</td>
<td>28%</td>
<td>20%</td>
<td>10%</td>
<td>6%</td>
</tr>
<tr>
<td>second</td>
<td>28%</td>
<td>32%</td>
<td>22%</td>
<td>12%</td>
<td>6%</td>
</tr>
<tr>
<td>third</td>
<td>20%</td>
<td>22%</td>
<td>32%</td>
<td>18%</td>
<td>10%</td>
</tr>
<tr>
<td>fourth</td>
<td>12%</td>
<td>12%</td>
<td>18%</td>
<td>38%</td>
<td>20%</td>
</tr>
<tr>
<td>fifth</td>
<td>6%</td>
<td>6%</td>
<td>10%</td>
<td>20%</td>
<td>60%</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>QuickSort (random pivot)</td>
<td>
<table>
<tbody>
<tr>
<td>position/number</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>first</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
</tr>
<tr>
<td>second</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
</tr>
<tr>
<td>third</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
</tr>
<tr>
<td>fourth</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
</tr>
<tr>
<td>fifth</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
<td>20%</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>MergeSort</td>
<td>
<table>
<tbody>
<tr>
<td>position/number</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>first</td>
<td>24%</td>
<td>24%</td>
<td>26%</td>
<td>12%</td>
<td>12%</td>
</tr>
<tr>
<td>second</td>
<td>26%</td>
<td>24%</td>
<td>18%</td>
<td>16%</td>
<td>16%</td>
</tr>
<tr>
<td>third</td>
<td>18%</td>
<td>18%</td>
<td>22%</td>
<td>20%</td>
<td>20%</td>
</tr>
<tr>
<td>fourth</td>
<td>16%</td>
<td>16%</td>
<td>18%</td>
<td>26%</td>
<td>26%</td>
</tr>
<tr>
<td>fifth</td>
<td>16%</td>
<td>16%</td>
<td>18%</td>
<td>26%</td>
<td>26%</td>
</tr>
</tbody>
</table>
</td>
</tr>
<tr>
<td>SelectionSort</td>
<td>
<table>
<tbody>
<tr>
<td>position/number</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>first</td>
<td>6%</td>
<td>6%</td>
<td>12%</td>
<td>26%</td>
<td>50%</td>
</tr>
<tr>
<td>second</td>
<td>12%</td>
<td>12%</td>
<td>20%</td>
<td>32%</td>
<td>24%</td>
</tr>
<tr>
<td>third</td>
<td>20%</td>
<td>20%</td>
<td>26%</td>
<td>20%</td>
<td>12%</td>
</tr>
<tr>
<td>fourth</td>
<td>30%</td>
<td>30%</td>
<td>20%</td>
<td>12%</td>
<td>6%</td>
</tr>
<tr>
<td>fifth</td>
<td>30%</td>
<td>30%</td>
<td>20%</td>
<td>12%</td>
<td>6%</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table>
<p>The distributions are significantly different among these sorts.  QuickSort appears to provide a uniform distribution.  I believe that this is because QuickSort will only compare a particular pair of elements once, whereas each of the other sorting algorithms may compare a given pair of elements more than once (and with a random comparison function, receive a different result from one time to the next).</p>
<p>Here is the Mathematica notebook I used to generate this data: <a href="http://2718.us/blog/wp-content/uploads/2010/02/testing-randomize-by-sorting-2.nb">Randomize by Sorting.nb</a>.  As noted in the file, some of the code for the sorting algorithms was taken from other locations and may be/is subject to their copyrights and/or license terms (I reasonably believe that this use complies with their licenses and/or constitutes fair use.  Also, some algorithms exhibited improper behavior when trying to sort lists with duplicate entries using a normal comparison function as noted in the file, though this should have no effect on the data above.</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/02/24/randomizing-by-random-comparison-sorting-revisited/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The EU Browser Ballot and Random Sorting</title>
		<link>http://2718.us/blog/2010/02/23/the-eu-browser-ballot-and-random-sorting/</link>
		<comments>http://2718.us/blog/2010/02/23/the-eu-browser-ballot-and-random-sorting/#comments</comments>
		<pubDate>Wed, 24 Feb 2010 02:09:44 +0000</pubDate>
		<dc:creator>2718.us</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[browser ballot]]></category>
		<category><![CDATA[eu]]></category>
		<category><![CDATA[european union]]></category>
		<category><![CDATA[ie8]]></category>
		<category><![CDATA[internet explorer]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[mathematica]]></category>
		<category><![CDATA[mathematics]]></category>
		<category><![CDATA[microsoft]]></category>
		<category><![CDATA[statistics]]></category>

		<guid isPermaLink="false">http://2718.us/blog/?p=212</guid>
		<description><![CDATA[An Ars Technica &#8220;etc&#8221; post linked to a TechCrunch article (apparently based on a Slovakian article, but I didn&#8217;t look into the Slovakian article to be sure) that talks about the ordering of the browsers in Microsoft&#8217;s EU Browser Ballot not being uniformly distributed.  At a glance at the Javascript that does the randomizing of [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://arstechnica.com/microsoft/news/2010/02/-the-javascript-code-on.ars">An Ars Technica &#8220;etc&#8221; post</a> linked to <a href="http://techcrunch.com/2010/02/22/microsoft-ballot-screen/">a TechCrunch article</a> (apparently based on <a href="http://www.dsl.sk/article.php?article=8770">a Slovakian article</a>, but I didn&#8217;t look into the Slovakian article to be sure) that talks about the ordering of the browsers in <a href="http://www.browserchoice.eu/BrowserChoice/browserchoice_en.htm">Microsoft&#8217;s EU Browser Ballot</a> not being uniformly distributed.  At a glance at the Javascript that does the randomizing of the browsers (randomly orders the top 5, and randomly orders the rest), it appears to randomize by calling the Javascript array sort with a comparison function that returns &lt; half the time and &gt; the other half of the time.  I believe that this is likely the underlying cause of the non-uniformity of the orderings.</p>
<p><a href="http://www.javascriptkit.com/javatutors/arraysort.shtml">The second result</a> in <a href="http://www.google.com/search?sourceid=chrome&amp;ie=UTF-8&amp;q=javascript+sort">a google search for &#8220;javascript sort&#8221;</a> says:</p>
<blockquote><p>To randomize the order of the elements within an array, what we need is the body of our sortfunction to return a number that is randomly &lt;0, 0, or &gt;0, irrespective to the relationship between &#8220;a&#8221; and &#8220;b&#8221;. The below will do the trick:</p>
<pre>//Randomize the order of the array:
var myarray=[25, 8, "George", "John"]
myarray.sort(function() {return 0.5 - Math.random()}) //Array elements now scrambled</pre>
</blockquote>
<p>This is almost exactly the method of randomization used in the browser ballot javascript.</p>
<p>To test the results of this randomization technique, I applied it 1,000,000 times to the list {0,1,2,3,4} in Mathematica and tabulated the relative frequencies of each number in each position.  (Rounded to the nearest whole %).</p>
<table>
<tbody>
<tr>
<td>position/number</td>
<td>0</td>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>first</td>
<td>18%</td>
<td>12%</td>
<td>12%</td>
<td>12%</td>
<td>47%</td>
</tr>
<tr>
<td>second</td>
<td>18%</td>
<td>24%</td>
<td>18%</td>
<td>18%</td>
<td>24%</td>
</tr>
<tr>
<td>third</td>
<td>20%</td>
<td>21%</td>
<td>27%</td>
<td>20%</td>
<td>12%</td>
</tr>
<tr>
<td>fourth</td>
<td>22%</td>
<td>22%</td>
<td>22%</td>
<td>28%</td>
<td>6%</td>
</tr>
<tr>
<td>fifth</td>
<td>22%</td>
<td>22%</td>
<td>22%</td>
<td>22%</td>
<td>12%</td>
</tr>
</tbody>
</table>
<p>At a glance, it appears that the distribution is far from uniform.  My quick attempt at re-learning how to use the Χ<sup>2</sup> test gave a probability less than 1×10<sup>-100000</sup> that this data matched a uniform distribution (if someone can confirm/fix that, please comment).</p>
<p>I used the Mathematica Sort[] command to do the sorting.  I don&#8217;t know what algorithm that uses.  It appears that the algorithm used by Javascript&#8217;s sort() varies from browser to browser, though the browser ballot would be displayed in IE8 by default.  I suspect that the distribution is highly dependent on the sorting algorithm used, though I cannot readily verify it [<em>edit</em>: <a href="http://2718.us/blog/2010/02/24/randomizing-by-random-comparison-sorting-revisited/">I verified it</a>].  Regardless, this seems to be a very poor way to generate a random ordering.</p>
]]></content:encoded>
			<wfw:commentRss>http://2718.us/blog/2010/02/23/the-eu-browser-ballot-and-random-sorting/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

