<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?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:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" xml:lang="en" xml:base="http://extralogical.net/wp-atom.php">
	<title type="text">Extralogical</title>
	<subtitle type="text" />

	<updated>2010-01-07T12:08:38Z</updated>
	<generator uri="http://wordpress.org/" version="3.0-alpha">WordPress</generator>

	<link rel="alternate" type="text/html" href="http://extralogical.net" />
	<id>http://extralogical.net/feed/</id>
	

			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/extralogical" /><feedburner:info uri="extralogical" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry>
		<author>
			<name>Benedict</name>
						<uri>http://extralogical.net</uri>
					</author>
		<title type="html"><![CDATA[Ruby One Niner]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/extralogical/~3/lTtInH8XAR0/" />
		<id>http://extralogical.net/?p=499</id>
		<updated>2010-01-07T12:08:38Z</updated>
		<published>2009-07-15T17:03:31Z</published>
		<category scheme="http://extralogical.net" term="Uncategorised" /><category scheme="http://extralogical.net" term="mod_rails" /><category scheme="http://extralogical.net" term="Mongrel" /><category scheme="http://extralogical.net" term="Paper Trail" /><category scheme="http://extralogical.net" term="Ruby" /><category scheme="http://extralogical.net" term="Ruby on Rails" /><category scheme="http://extralogical.net" term="Ubuntu" />		<summary type="html"><![CDATA[A brief guide to replacing an older version of Ruby with Ruby 1.9 on Ubuntu servers. Contains discussion of a few pitfalls and how to avoid them.]]></summary>
		<content type="html" xml:base="http://extralogical.net/2009/07/ruby-one-niner/">&lt;p&gt;All my server&amp;#8217;s Ruby applications, most notably my &lt;a href="http://books.extralogical.net/"&gt;books site&lt;/a&gt;, have been running on 1.9.1 for over a month now. During the process of upgrading Ruby I jotted down a few notes on the process I followed, the problems I encountered and the ways in which I solved them. None of this is new information, but hopefully bringing these solutions together will be of use to those with similar setups, or at least to myself in the future.&lt;/p&gt;
&lt;h3&gt;Installing Ruby&lt;/h3&gt;
&lt;p&gt;I installed Ruby 1.9.1 on an Ubuntu 8.04 (&lt;abbr title="Long Term Support"&gt;LTS&lt;/abbr&gt;) server, which was reasonably simple in and of itself, although the Ruby ecosystem as a whole has clearly not quite caught up to the new &lt;abbr title="Virtual Machine"&gt;VM&lt;/abbr&gt;.&lt;/p&gt;
&lt;p&gt;Ruby 1.8.6 is still the default version of Ruby available on the Ubuntu package system, and while there is a version of Ruby 1.9 available, it&amp;#8217;s quite out of date. For this reason, I recommend compiling it by hand from the source code provided on the Ruby website. This has the additional benefit of making upgrading your version of Ruby independent of the Ubuntu packaging hierarchy, which can be somewhat slow to update theirs.&lt;/p&gt;
&lt;p&gt;Uninstalling Ruby 1.8.6&amp;#8212;assuming it was installed with &lt;code&gt;aptitude&lt;/code&gt;&amp;#8212;is extremely simple:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo aptitude remove ruby1.8&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The package manager will pick up on the fact that &lt;code&gt;rdoc&lt;/code&gt;, &lt;code&gt;ri&lt;/code&gt; and &lt;code&gt;irb&lt;/code&gt; depend on Ruby, and uninstall them as well as &lt;code&gt;ruby1.8-dev&lt;/code&gt; and &lt;code&gt;libreadline-ruby1.8&lt;/code&gt; which will be unused when &lt;code&gt;ruby1.8&lt;/code&gt; is gone.&lt;/p&gt;
&lt;p&gt;If you&amp;#8217;re following these instructions, make sure you use the &lt;a href="http://www.ruby-lang.org/en/downloads/"&gt;latest stable version&lt;/a&gt; from the Ruby site, not the one I list here. Given that newer versions are likely to fix bugs and security vulnerabilities, this is extremely important. Blindly copying and pasting shell commands is a sure-fire way to create problems for yourself.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;cd /usr/local/src/
sudo curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p243.tar.gz
sudo tar xzvf ruby-1.9.1-p243.tar.gz
cd ruby-1.9.1-p243/
sudo ./configure
sudo make
sudo make install&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Installing gems&lt;/h3&gt;
&lt;p&gt;The RubyGems packaging system is built into Ruby 1.9, but quite a few gems are not yet compatible with the new &lt;abbr title="Virtual Machine"&gt;VM&lt;/abbr&gt;. There are lots of helpful notes in &lt;a href="http://frozenplague.net/2009/01/ruby-191-rubygems-rails/"&gt;this blog post&lt;/a&gt;, although thankfully not all of them still apply.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://isitruby19.com/"&gt;Is it Ruby 1.9?&lt;/a&gt; generally gives one a good sense of whether just running &lt;code&gt;gem install foo&lt;/code&gt; will work, but is often lacking when it doesn’t. Some research will likely be required if you have a lot of gems.&lt;/p&gt;
&lt;h4&gt;Some gems just worked&lt;/h4&gt;
&lt;pre&gt;&lt;code&gt;sudo gem install hpricot \
                 rake \
                 rack \
                 rails \
                 will_paginate \
                 rdiscount \
                 fastthread \
                 passenger&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;Mongrel&lt;/h4&gt;
&lt;p&gt;Getting Mongrel to even run was ludicrously complicated. Here are the steps I followed to do so, but before I list them I should note that I don&amp;#8217;t think that this is generally worth doing, unless for some reason you can&amp;#8217;t possibly switch to an alternative web server such as &lt;a href="http://www.modrails.com/"&gt;Passenger&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The changes you&amp;#8217;ll need to make to the Mongrel source code concern references to the objects of the underlying C implementation: since Ruby 1.9 is based on an entirely new virtual machine, any direct references to &lt;a href="http://en.wikipedia.org/wiki/Ruby_MRI"&gt;&lt;abbr title="Matz's Ruby Interpreter"&gt;MRI&lt;/abbr&gt;&lt;/a&gt; objects have to be changed to instead refer to &lt;a href="http://www.atdot.net/yarv/"&gt;&lt;abbr title="Yet Another Ruby VM"&gt;YARV&lt;/abbr&gt;&lt;/a&gt; ones.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Hack &lt;code&gt;ext/http11/http11.c&lt;/code&gt; file to replace references to &lt;code&gt;RSTRING(foo)-&amp;gt;ptr&lt;/code&gt; with &lt;code&gt;RSTRING_PTR(foo)&lt;/code&gt;, &lt;code&gt;RSTRING(bar)-&amp;gt;len&lt;/code&gt; with &lt;code&gt;RSTRING_LEN(bar)&lt;/code&gt;, &lt;code&gt;RARRAY(baz)-&amp;gt;ptr&lt;/code&gt; with &lt;code&gt;RARRAY_PTR(baz)&lt;/code&gt; and &lt;code&gt;RARRAY(qux)-&amp;gt;len&lt;/code&gt; with &lt;code&gt;RARRAY_LEN(qux)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;sudo ruby setup.rb &amp;amp;&amp;amp; sudo make &amp;amp;&amp;amp; sudo make install&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Copy the &lt;code&gt;mongrel.gemspec&lt;/code&gt; file to your RubyGems specifications directory as &lt;code&gt;mongrel-1.1.5.gemspec&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Obviously those changes won’t work on Ruby &amp;lt; 1.9. Ryan Bigg has a &lt;a href="http://github.com/radar/mongrel/"&gt;1.9-compatible version&lt;/a&gt;, although I haven’t tried it personally.&lt;/p&gt;
&lt;p&gt;While I did get Mongrel working, it didn’t play nicely with Rails 2.3.2 at all, so in the end I just dropped it and installed Passenger instead, which is &lt;a href="http://blog.phusion.nl/2009/02/02/getting-ready-for-ruby-191/"&gt;much better&lt;/a&gt; in this regard, and a lot lower-maintenance. After removing Mongrel I cleaned up the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Config files in &lt;code&gt;/etc/mongrel_cluster/&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;A symlink to one of the gem files in &lt;code&gt;/etc/init.d/&lt;/code&gt; to restart the cluster if the server rebooted&lt;/li&gt;
&lt;li&gt;A load of &lt;a href="http://httpd.apache.org/docs/2.2/mod/mod_proxy_balancer.html"&gt;&lt;code&gt;mod_proxy_balancer&lt;/code&gt;&lt;/a&gt; cruft in my Apache configs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Coda Hale’s &lt;a href="http://blog.codahale.com/2006/06/19/time-for-a-grown-up-server-rails-mongrel-apache-capistrano-and-you/"&gt;grown up server&lt;/a&gt; was a great hack, but its time is past. Slicehost have good articles on &lt;a href="http://articles.slicehost.com/2008/5/1/ubuntu-hardy-mod_rails-installation"&gt;installing Passenger&lt;/a&gt; and using it to &lt;a href="http://articles.slicehost.com/2008/5/1/ubuntu-hardy-using-mod_rails-to-serve-your-application"&gt;serve your application&lt;/a&gt;, but it’s basically very straightforward.&lt;/p&gt;
&lt;h4&gt;MySQL&lt;/h4&gt;
&lt;p&gt;The MySQL gem on RubyForge is outdated and not completely compatible with Ruby 1.9. The updated gem has to be &lt;a href="http://www.tmtm.org/en/mysql/ruby/"&gt;built by hand&lt;/a&gt;, which is a fairly uncomplicated process.&lt;/p&gt;
&lt;h3&gt;Updating applications&lt;/h3&gt;
&lt;p&gt;Most of my application code just worked. The only real changes I had to deal with were those concerning the new &lt;code&gt;String&lt;/code&gt; class, but these are well documented and shouldn&amp;#8217;t be a surprise to anyone upgrading an application or library to work with 1.9. If in future I run across any other issues, I&amp;#8217;ll add them in a supplementary section below.&lt;/p&gt;
&lt;h4&gt;The new String class&lt;/h4&gt;
&lt;p&gt;James Edward Gray II has written some very helpful articles on Ruby 1.9’s &lt;a href="http://blog.grayproductions.net/articles/ruby_19s_string"&gt; new &lt;code&gt;String&lt;/code&gt; class&lt;/a&gt; and &lt;a href="http://blog.grayproductions.net/articles/ruby_19s_three_default_encodings"&gt;default encodings&lt;/a&gt;. They proved invaluable when trying to track down bugs in code written for Ruby 1.8.6 (most of the fruits of my labours in this regard are visible in &lt;a href="http://github.com/ionfish/urlify/"&gt;URLify&lt;/a&gt;).&lt;/p&gt;
&lt;h4&gt;Backwards-incompatible Tempfile changes&lt;/h4&gt;
&lt;p&gt;After upgrading to Ruby 1.9.1-p243, &lt;a href="http://books.extralogical.net/"&gt;Books on Extralogical&lt;/a&gt; died, with Passenger reporting an &lt;code&gt;IOError&lt;/code&gt;. &lt;a href="http://redmine.ruby-lang.org/issues/show/1494"&gt;Apparently&lt;/a&gt; a change was made to &lt;code&gt;Tempfile#unlink&lt;/code&gt; to fix some issues with the library on Windows, resulting in a behaviour change that &lt;a href="http://groups.google.com/group/rack-devel/browse_thread/thread/a2aab3a4720f34c4?pli=1"&gt;broke programs&lt;/a&gt; on *nix systems. I edited the library file and reverted the change, which fixed the application. Hopefully a future version of Ruby will revert this change, or it will be fixed at the library level in Rack. Here&amp;#8217;s the path to the file in question on my system:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/usr/local/lib/ruby/1.9.1/tempfile.rb&lt;/code&gt;&lt;/pre&gt;
&lt;h5&gt;Update, 26&lt;sup&gt;th&lt;/sup&gt; August 2009&lt;/h5&gt;
&lt;p&gt;This behaviour has &lt;a href="http://redmine.ruby-lang.org/repositories/revision/ruby-19?rev=24662"&gt;been reverted&lt;/a&gt; for the Ruby 1.9 development branch, and the fix will be backported to the 1.9.1 branch. Many thanks to Hongli Lai for pursuing this.&lt;/p&gt;
&lt;h5&gt;Update, 7&lt;sup&gt;th&lt;/sup&gt; January 2009&lt;/h5&gt;
&lt;p&gt;Having switched to &lt;a href="http://gemcutter.org/"&gt;Gemcutter&lt;/a&gt; as my primary gem source, I&amp;#8217;ve removed the GitHub gem source details from the article.&lt;/p&gt;
&lt;h3&gt;In conclusion&lt;/h3&gt;
&lt;p&gt;In the end, only two things caused me any trouble: installing Mongrel, and installing MySQL. The latter was relatively painless once I found the right version of the library; I really don’t know why the newer version isn’t available on RubyForge. The former was a complete pain, and my advice is to scrap any Mongrel-based setup and install Passenger from the get-go&amp;#8212;it’ll be quicker than trying to hack your old setup back together. Now that Passenger is &lt;a href="http://blog.phusion.nl/2009/04/16/phusions-one-year-anniversary-gift-phusion-passenger-220/"&gt;available for nginx&lt;/a&gt; as well as Apache, the case is thoroughly compelling.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/extralogical/~4/lTtInH8XAR0" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://extralogical.net/2009/07/ruby-one-niner/#comments" thr:count="9" />
		<link rel="replies" type="application/atom+xml" href="http://extralogical.net/2009/07/ruby-one-niner/feed/" thr:count="9" />
		<thr:total>9</thr:total>
	<feedburner:origLink>http://extralogical.net/2009/07/ruby-one-niner/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Benedict</name>
						<uri>http://extralogical.net</uri>
					</author>
		<title type="html"><![CDATA[Paper Cuts]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/extralogical/~3/N_Ix_ChkWBE/" />
		<id>http://extralogical.net/?p=481</id>
		<updated>2009-08-23T10:04:52Z</updated>
		<published>2009-06-30T00:19:01Z</published>
		<category scheme="http://extralogical.net" term="Uncategorised" /><category scheme="http://extralogical.net" term="Paper Trail" /><category scheme="http://extralogical.net" term="Ruby on Rails" /><category scheme="http://extralogical.net" term="URLify" />		<summary type="html"><![CDATA[A brief update on some changes to Paper Trail, the application I use to keep track of my reading.]]></summary>
		<content type="html" xml:base="http://extralogical.net/2009/06/paper-cuts/">&lt;p&gt;Today I removed a few sharp edges from &lt;a href="http://extralogical.net/2008/11/bookkeeping/"&gt;Paper Trail&lt;/a&gt;, the web application I use to keep track of &lt;a href="http://books.extralogical.net/"&gt;my reading&lt;/a&gt;. It&amp;#8217;s cheering to cross a couple of items off &lt;a href="http://extralogical.net/papertrail/"&gt;the issues list&lt;/a&gt;, although there always seem to be new ones to replace them.&lt;/p&gt;
&lt;h3&gt;Removing authentication&lt;/h3&gt;
&lt;p&gt;As a single-user application, the idea of having an entire authentication system in Paper Trail always seemed ridiculous. Obviously some form of authentication was required, so I threw together a simple and horribly insecure system based on Ryan Bates&amp;#8217; &lt;a href="http://railscasts.com/episodes/21-super-simple-authentication"&gt;Super Simple Authentication&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That has now been replaced by a single naïve check&amp;#8212;was the request made over &lt;abbr title="Secure Sockets Layer"&gt;SSL&lt;/abbr&gt; or not? Clearly this depends on the web server only allowing &lt;a href="http://httpd.apache.org/docs/2.2/mod/mod_auth_digest.html"&gt;authenticated users&lt;/a&gt; to access the site via &lt;abbr title="Hypertext Transfer Protocol Secure"&gt;HTTPS&lt;/abbr&gt;, but since no one other than myself needs to access the site securely, this seems a reasonable approach, albeit not one that would work for any application requiring multiple users to authenticate. Regardless, it&amp;#8217;s cheering to be able to simultaneously increase security and reduce the codebase.&lt;/p&gt;
&lt;h3&gt;Dropping accents with URLify&lt;/h3&gt;
&lt;p&gt;One thing that Paper Trail needed right from the start was a way to simply and cleanly replace letters with diacritics, e.g. replacing &amp;#8220;é&amp;#8221; with &amp;#8220;e&amp;#8221;. On a couple of occasions I&amp;#8217;ve wanted to use the small conversion library I wrote in other applications, so extracting it into an external library was a natural move. It&amp;#8217;s called &lt;a href="http://github.com/ionfish/urlify/"&gt;URLify&lt;/a&gt;, and its tiny public &lt;abbr title="Application Programming Interface"&gt;API&lt;/abbr&gt; is explained in the &lt;code&gt;README&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Multiple authors&lt;/h3&gt;
&lt;p&gt;The other major piece of functionality added since the initial launch was support for multiple authors, which was actually completed some months ago. Thus far I&amp;#8217;ve only used it for &lt;a href="http://books.extralogical.net/books/all_the_presidents_men"&gt;&lt;cite&gt;All the President&amp;#8217;s Men&lt;/cite&gt;&lt;/a&gt;, although I suspect it will be more useful in the future as I start finishing&amp;#8212;and not just starting&amp;#8212;various books in my technical library.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/extralogical/~4/N_Ix_ChkWBE" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://extralogical.net/2009/06/paper-cuts/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://extralogical.net/2009/06/paper-cuts/feed/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://extralogical.net/2009/06/paper-cuts/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Benedict</name>
						<uri>http://extralogical.net</uri>
					</author>
		<title type="html"><![CDATA[Generating CSS With Stylish]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/extralogical/~3/wowlETMVMRY/" />
		<id>http://extralogical.net/?p=448</id>
		<updated>2009-05-07T19:15:56Z</updated>
		<published>2009-05-07T19:15:56Z</published>
		<category scheme="http://extralogical.net" term="Uncategorised" /><category scheme="http://extralogical.net" term="CSS" /><category scheme="http://extralogical.net" term="Ruby" /><category scheme="http://extralogical.net" term="Stylish" />		<summary type="html"><![CDATA[<a href="http://ionfish.github.com/stylish/">Stylish</a> is a small Ruby library for generating CSS code.]]></summary>
		<content type="html" xml:base="http://extralogical.net/2009/05/generating-css-with-stylish/">&lt;p&gt;Writing &lt;abbr title="Cascading Stylesheets"&gt;CSS&lt;/abbr&gt; can be a frustrating experience. Browser incompatibilities bedevil one&amp;#8217;s every move; the speed with which improvements in the specification are actually implemented by vendors is glacial; and everywhere, one is forced to copy and paste code with minor variations, simply to work around some fundamental limitations in the language.&lt;/p&gt;
&lt;p&gt;There seems to be little that developers can do to rectify the first two problems, but solving the third is within our grasp. &lt;a href="http://ionfish.github.com/stylish/"&gt;Stylish&lt;/a&gt; is my attempt at doing so. It&amp;#8217;s a small Ruby library which allows one to generate stylesheets programmatically, via the use of a simple but powerful &lt;abbr title="Domain-Specific Language"&gt;DSL&lt;/abbr&gt;.&lt;/p&gt;
&lt;p&gt;When attempting to reduce code duplication (and the transcription errors which accompany it), two major weaknesses in CSS spring immediately to mind: the lack of variables, and the lack of iteration. Consider the common use case of developing minor variations on a site&amp;#8217;s style:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;.autumn a {color:#90211c;}
.autumn a:hover {color:#bb5f1b;}

.winter a {color:#16335f;}
.winter a:hover {color:#5a9bce;}

.spring a {color:#448e1c;}
.spring a:hover {color:#6bcf35;}

.summer a {color:#c8ad1a;}
.summer a:hover {color:#d3482c;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we have four groups of rules, each with the same pattern but slightly different values for their selectors and declaration values. Using Stylish, we can write a small snippet of code to generate the correct structure, giving us a template which we can pass variables into.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;style = Stylish.generate do
  rule :season do
    a :color =&amp;gt; :link
    rule "a:hover", :color =&amp;gt; :hover
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we need to map those variables&amp;#8211;&lt;code&gt;:season&lt;/code&gt;, &lt;code&gt;:link&lt;/code&gt; and &lt;code&gt;:hover&lt;/code&gt;&amp;#8211;to some actual values. Note that variables are only supported for selector and declaration values, not declaration properties.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;seasons = [{:season =&amp;gt; ".autumn", :link =&amp;gt; "90211c", :hover =&amp;gt; "bb5f1b"},
           {:season =&amp;gt; ".winter", :link =&amp;gt; "16335f", :hover =&amp;gt; "5a9bce"},
           {:season =&amp;gt; ".spring", :link =&amp;gt; "448e1c", :hover =&amp;gt; "6bcf35"},
           {:season =&amp;gt; ".summer", :link =&amp;gt; "c8ad1a", :hover =&amp;gt; "d3482c"}]&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Finally, we can generate some CSS code. Calling to the &lt;code&gt;to_s&lt;/code&gt; method on the &lt;code&gt;style&lt;/code&gt; object serialises the structure we initially created, filling in the variables with concrete values from our mappings.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;seasons.each do |season|
  puts style.to_s(season)
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The entire script &lt;a href="http://gist.github.com/101383"&gt;is available&lt;/a&gt;; a couple of other examples can be found &lt;a href="http://github.com/ionfish/stylish/"&gt;in the project&lt;/a&gt;&amp;#8217;s &lt;code&gt;example/&lt;/code&gt; directory. Installing Stylish, assuming that you have Ruby and Rubygems, is as simple as typing the following command into your terminal.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo gem install ionfish-stylish -s http://gems.github.com&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I&amp;#8217;ve published a fairly comprehensive introductory tutorial on the &lt;a href="http://ionfish.github.com/stylish/"&gt;Stylish documentation site&lt;/a&gt;. It eases the reader into developing with Stylish through a series of code examples which demonstrate all the main features of the stylesheet generator.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/extralogical/~4/wowlETMVMRY" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://extralogical.net/2009/05/generating-css-with-stylish/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://extralogical.net/2009/05/generating-css-with-stylish/feed/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://extralogical.net/2009/05/generating-css-with-stylish/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Benedict</name>
						<uri>http://extralogical.net</uri>
					</author>
		<title type="html"><![CDATA[Big Exit]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/extralogical/~3/ZxjUYtkgDcE/" />
		<id>http://extralogical.net/?p=422</id>
		<updated>2009-01-23T15:16:39Z</updated>
		<published>2009-01-23T15:16:39Z</published>
		<category scheme="http://extralogical.net" term="Uncategorised" /><category scheme="http://extralogical.net" term="Haskell" /><category scheme="http://extralogical.net" term="JavaScript" /><category scheme="http://extralogical.net" term="Lisp" /><category scheme="http://extralogical.net" term="MySQL" /><category scheme="http://extralogical.net" term="programming" /><category scheme="http://extralogical.net" term="REPL" /><category scheme="http://extralogical.net" term="Ruby" /><category scheme="http://extralogical.net" term="Scheme" /><category scheme="http://extralogical.net" term="SQLite" />		<summary type="html"><![CDATA[Exit procedures for various REPLs.]]></summary>
		<content type="html" xml:base="http://extralogical.net/2009/01/big-exit/">&lt;p&gt;Most sensible programming languages, and plenty of other applications, have an &lt;a href="http://en.wikipedia.org/wiki/REPL"&gt;&lt;abbr title="Real-eval-print loop"&gt;REPL&lt;/abbr&gt;&lt;/a&gt;, or read-eval-print loop. They&amp;#8217;re a good way of trying out simple commands, running scripts and so on. The trouble is, I can never remember how to leave the damn things, because they all have different ways of issuing the quit command.&lt;/p&gt;
&lt;p&gt;Language designers like &amp;#8216;Quit&amp;#8217; to be a command or procedure in the language itself; something syntactically and semantically correct that wouldn&amp;#8217;t be out of place in a file of source code written in that language. In principle this is exactly right; in practice, it means every &lt;abbr title="Real-eval-print loop"&gt;REPL&lt;/abbr&gt; implements &amp;#8216;Quit&amp;#8217; differently, and as soon as you use more than three or four, they become harder and harder to remember. Here are a few I use fairly often.&lt;/p&gt;
&lt;h3&gt;Ruby (&lt;abbr title="Interactive Ruby"&gt;IRB&lt;/abbr&gt;)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; exit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this context, &lt;code&gt;exit&lt;/code&gt; just looks like a keyword, but it&amp;#8217;s actually a method on the &lt;code&gt;main&lt;/code&gt; &lt;a href="http://teera.seriyagroup.com/blog/index.php/2008/07/25/everything-is-an-object-in-ruby/"&gt;object&lt;/a&gt;. If you call &lt;code&gt;self.exit&lt;/code&gt; at the &lt;abbr title="Interactive Ruby"&gt;IRB&lt;/abbr&gt; prompt it&amp;#8217;ll have the same effect.&lt;/p&gt;
&lt;h3&gt;JavaScript (Rhino)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; quit();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;A function call; entering &lt;code&gt;quit&lt;/code&gt; without the parentheses will just return the function, not call it.&lt;/p&gt;
&lt;h3&gt;Scheme (mzscheme)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; (exit)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Parentheses required, of course, since Scheme is a &lt;a href="http://www.defmacro.org/ramblings/lisp.html"&gt;Lisp&lt;/a&gt; and &lt;code&gt;exit&lt;/code&gt; is a procedure.&lt;/p&gt;
&lt;h3&gt;Haskell (&lt;abbr title="Glasgow Haskell Compiler (interactive mode)"&gt;GHCi&lt;/abbr&gt;)&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; :quit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This one&amp;#8217;s a &lt;a href="http://www.haskell.org/ghc/docs/latest/html/users_guide/ghci-commands.html"&gt;command&lt;/a&gt;, as opposed to a statement in the language (Haskell is an essentially declarative language, and thus involves making statements rather than calling commands). There are a lot of useful commands in &lt;abbr title="Glasgow Haskell Compiler (interactive mode)"&gt;GHCi&lt;/abbr&gt;; type &lt;code&gt;:?&lt;/code&gt; and it&amp;#8217;ll list them for you.&lt;/p&gt;
&lt;h3&gt;MySQL&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; \q&lt;/code&gt;
&lt;code&gt;&amp;gt; quit&lt;/code&gt;
&lt;code&gt;&amp;gt; \quit&lt;/code&gt;
&lt;code&gt;&amp;gt; exit&lt;/code&gt;
&lt;code&gt;&amp;gt; \exit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These all work. There might be more.&lt;/p&gt;
&lt;h3&gt;SQLite&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; .exit&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The dot prefix distinguishes SQLite commands from &lt;abbr title="Structured Query Language"&gt;SQL&lt;/abbr&gt; queries.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/extralogical/~4/ZxjUYtkgDcE" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://extralogical.net/2009/01/big-exit/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://extralogical.net/2009/01/big-exit/feed/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://extralogical.net/2009/01/big-exit/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Benedict</name>
						<uri>http://extralogical.net</uri>
					</author>
		<title type="html"><![CDATA[Bookkeeping]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/extralogical/~3/Ofeiu0GzmXc/" />
		<id>http://extralogical.net/?p=298</id>
		<updated>2009-08-23T10:04:13Z</updated>
		<published>2008-11-14T01:35:00Z</published>
		<category scheme="http://extralogical.net" term="Uncategorised" /><category scheme="http://extralogical.net" term="books" /><category scheme="http://extralogical.net" term="JavaScript" /><category scheme="http://extralogical.net" term="Paper Trail" /><category scheme="http://extralogical.net" term="Ruby on Rails" />		<summary type="html"><![CDATA[Paper Trail is a small Ruby on Rails application which I wrote to keep track of my reading.]]></summary>
		<content type="html" xml:base="http://extralogical.net/2008/11/bookkeeping/">&lt;p&gt;Quite some time ago, I started work on a program to help me keep track of my reading. It&amp;#8217;s not entirely clear to me, even now, whether it was meant to represent a litany of achievement, to cement the ideas I read about by jotting them down, or whether it was just an exercise in literary accountancy. What is certain is that I wanted two things: a working piece of software, and a testbed for any number of new skills and techniques.&lt;/p&gt;
&lt;p&gt;I&amp;#8217;ve actually been using &lt;a href="http://extralogical.net/projects/papertrail/"&gt;Paper Trail&lt;/a&gt; for a few months now, and the sharp-eyed amongst you will have noticed the Books link at the top of the site. &lt;a href="http://books.extralogical.net/"&gt;Books on Extralogical&lt;/a&gt; is a record of the books I read, and secondarily a set of brief reviews. I&amp;#8217;d like to get more of them in the state that the &lt;a href="http://books.extralogical.net/books/hackers_and_painters"&gt;Hackers &amp;#038; Painters&lt;/a&gt; one is&amp;#8212;that&amp;#8217;s to say, a few paragraphs summarising what the book&amp;#8217;s about and my general reaction to it. Currently, too many of the reviews are lacking either a decent précis or any editorial content, or are just badly written. That being said, I actually dropped the requirement for a review during development because I found it stopped me adding the books as I read them.&lt;/p&gt;
&lt;p&gt;Paper Trail probably only works well in newer versions of Firefox, Safari, and possibly other advanced browsers. This is because it uses a bunch of &lt;abbr title="Cascading Stylesheets level 3"&gt;CSS3&lt;/abbr&gt; properties, and plenty of 2.1 ones that aren&amp;#8217;t supported in Internet Explorer 6. The main content should remain accessible, if not as visually appealing as it could be, in most older browsers.&lt;/p&gt;
&lt;p&gt;One exception is this &lt;a href="http://books.extralogical.net/graphs/frequency"&gt;histogram&lt;/a&gt; showing how many books I&amp;#8217;ve read per month over the past year. It&amp;#8217;s an &lt;abbr title="Scalable Vector Graphics"&gt;SVG&lt;/abbr&gt; image, which Internet Explorer and most older browsers don&amp;#8217;t support.&lt;/p&gt;
&lt;p&gt;Most of the work hasn&amp;#8217;t been on user-facing code at all, but on the writing side of things. There is no admin area: editing is integrated into the site proper. A logged-in user sees a few controls and can easily fix a typo here or rewrite a paragraph there. I&amp;#8217;ve striven to make things simple and seamless. There&amp;#8217;s a certain amount of JavaScript involved, with more to come as I add things like autocomplete to the authors field.&lt;/p&gt;
&lt;p&gt;Obviously when it comes to an interface, words only go so far. Far better to check out the &lt;a href="http://github.com/ionfish/papertrail/"&gt;source code&lt;/a&gt;, run it locally, and have a play around. It&amp;#8217;s an extremely simple application, but I think it achieves its modest aims reasonably well. The code is available under the &lt;abbr title="Gnu Public License version 2"&gt;GPL&lt;/abbr&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/extralogical/~4/Ofeiu0GzmXc" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://extralogical.net/2008/11/bookkeeping/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://extralogical.net/2008/11/bookkeeping/feed/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://extralogical.net/2008/11/bookkeeping/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Benedict</name>
						<uri>http://extralogical.net</uri>
					</author>
		<title type="html"><![CDATA[Theme Inheritance]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/extralogical/~3/2XS-aUkgtyA/" />
		<id>http://extralogical.net/?p=296</id>
		<updated>2009-01-13T13:35:39Z</updated>
		<published>2008-08-02T15:05:37Z</published>
		<category scheme="http://extralogical.net" term="Uncategorised" /><category scheme="http://extralogical.net" term="development" /><category scheme="http://extralogical.net" term="Tarski" /><category scheme="http://extralogical.net" term="WordPress" />		<summary type="html"><![CDATA[WordPress 2.7 will allow child themes to override the templates of its parent theme. In this article, I explore the ramifications and possible applications of this change.]]></summary>
		<content type="html" xml:base="http://extralogical.net/2008/08/theme-inheritance/">&lt;p&gt;When I first read about &lt;a href="http://comox.textdrive.com/pipermail/wp-hackers/2008-June/020430.html"&gt;WordPress child themes&lt;/a&gt; on the wp-hackers mailing list, I wondered why I hadn&amp;#8217;t realised that feature existed. One reason it hasn&amp;#8217;t been more widely publicised is that it wasn&amp;#8217;t, as it stood, terribly useful. All it allowed you to do was use the templates of one theme (the parent theme) and the stylesheet of another (the child theme). You couldn&amp;#8217;t use it to create a child theme which inherited most its template files from its parent theme, but overrode some with its own files. &lt;a href="http://trac.wordpress.org/changeset/8497"&gt;That has now been remedied&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Consequently, in WordPress 2.7 it will be possible to write child themes which add new templates, and override existing ones in the parent theme. This has drastic implications; Ian Stewart, who proposed the patch, thinks it &amp;#8220;&lt;a href="http://themeshaper.com/wordpress-27-theming-may-change-everything/"&gt;may change everything&lt;/a&gt;&amp;#8221;. It makes it much easier to create new themes, yes, but even more radically, it allows users to modify existing ones &lt;em&gt;without changing their code&lt;/em&gt;. They can modify their &lt;a href="http://tarskitheme.com/"&gt;Tarski&lt;/a&gt; installations to their heart&amp;#8217;s content, while still being able to take advantage of bug fixes and improvements.&lt;/p&gt;
&lt;h3&gt;New templates&lt;/h3&gt;
&lt;p&gt;Tarski doesn&amp;#8217;t come with a template for the &lt;a href="http://www.geekwithlaptop.com/projects/clean-archives/"&gt;Clean Archives plugin&lt;/a&gt;, although it used to, and &lt;a href="http://tarski.googlecode.com/svn/extras/templates/clean-archives.php"&gt;one is available&lt;/a&gt; from Tarski&amp;#8217;s &lt;code&gt;svn&lt;/code&gt; repository. But if you add it to your Tarski directory, you might forget to back it up when you upgrade (I&amp;#8217;ve done this a few times). So you create a child theme, which inherits from Tarski, and includes the Clean Archives template&amp;#8212;which will automatically appear in the list of available page templates.&lt;/p&gt;
&lt;h3&gt;Overriding parent templates&lt;/h3&gt;
&lt;p&gt;One thing a couple of people have requested in the past is more comprehensive author templates for Tarski, with photos, contact details and so on. I&amp;#8217;ve been loathe to add this, which leaves people in the position of having to hack the template, and then try copy their changes into the new template when they upgrade Tarski&amp;#8212;or worse, not upgrade at all. With a child theme they could just copy Tarski&amp;#8217;s &lt;code&gt;author.php&lt;/code&gt; template, make their changes, and override Tarski&amp;#8217;s template with their own. They could then upgrade safely without having to carry any changes across.&lt;/p&gt;
&lt;h3&gt;Frameworks&lt;/h3&gt;
&lt;p&gt;Greater possibilities are now also opened up for treating themes more like frameworks or plugins. Perhaps you love Tarski&amp;#8217;s feature set but hate the layout. Simple: keep the options page, the navbar selector, the numerous templating functions, but write your own templates. We may see themes that are more of a code library than a set of templates.&lt;/p&gt;
&lt;p&gt;No doubt there are plenty of applications I haven&amp;#8217;t even considered yet. It&amp;#8217;s time for your imaginations to take over: download the &lt;a href="http://wordpress.org/download/svn/"&gt;trunk version&lt;/a&gt; of WordPress, and start hacking.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/extralogical/~4/2XS-aUkgtyA" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://extralogical.net/2008/08/theme-inheritance/#comments" thr:count="1" />
		<link rel="replies" type="application/atom+xml" href="http://extralogical.net/2008/08/theme-inheritance/feed/" thr:count="1" />
		<thr:total>1</thr:total>
	<feedburner:origLink>http://extralogical.net/2008/08/theme-inheritance/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Benedict</name>
						<uri>http://extralogical.net</uri>
					</author>
		<title type="html"><![CDATA[The State of the Art]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/extralogical/~3/OLYjxBRHEx0/" />
		<id>http://extralogical.net/?p=278</id>
		<updated>2009-01-13T13:35:39Z</updated>
		<published>2008-07-19T16:36:55Z</published>
		<category scheme="http://extralogical.net" term="Uncategorised" /><category scheme="http://extralogical.net" term="development" /><category scheme="http://extralogical.net" term="JavaScript" /><category scheme="http://extralogical.net" term="PHP" /><category scheme="http://extralogical.net" term="Tarski" /><category scheme="http://extralogical.net" term="WordPress" />		<summary type="html"><![CDATA[WordPress 2.6, Tarski 2.2, the WordPress theme directory, <abbr title="PHP: Hypertext Preprocessor">PHP</abbr> and JavaScript development.]]></summary>
		<content type="html" xml:base="http://extralogical.net/2008/07/the-state-of-the-art/">&lt;p&gt;&lt;a href="http://wordpress.org/development/2008/07/wordpress-26-tyner/"&gt;WordPress 2.6&lt;/a&gt; is the kind of release I&amp;#8217;d like to see the WordPress team doing more often. It contains some clever stuff, like post revisions, along with a load of bug fixes, and it didn&amp;#8217;t take too long to develop. In the past WordPress has taken far too long between releases; a reasonably quick turnaround and a predictable release schedule make life a lot easier for those of us writing code that depends on the core.&lt;/p&gt;
&lt;p&gt;Matt was kind enough to mention me in the release notes, but in truth I hardly did anything. These days I seem to be so busy that keeping my own projects up to date is proving beyond me, let alone contributing to things like WordPress. Finally pushing &lt;a href="http://tarskitheme.com/2008/07/19/22-release/"&gt;Tarski 2.2&lt;/a&gt; out of the door was stressful enough to put me off continuing its development. I suspect that from this point on it&amp;#8217;s going to enter maintenance mode, hopefully keeping pace with WordPress development in terms of feature support, but no more.&lt;/p&gt;
&lt;p&gt;I had the pleasure of road-testing the &lt;a href="http://wordpress.org/development/2008/07/theme-directory/"&gt;new theme directory&lt;/a&gt; that &lt;a href="http://joseph.randomnetworks.com/"&gt;Joseph Scott&lt;/a&gt; has put so much hard work into. I&amp;#8217;m not sure yet how the &lt;abbr title="Application Programming Interface"&gt;API&lt;/abbr&gt; is going to work, but I imagine we&amp;#8217;ll see update notices and one-click upgrades just like those for plugins. This will mean I&amp;#8217;ll be able to drop Tarski&amp;#8217;s own update mechanism, which will make the core code a little bit leaner and remove what&amp;#8217;s proved to be an ongoing headache, despite the hard work of those who&amp;#8217;ve helped me debug the various problems it&amp;#8217;s had. You can grab &lt;a href="http://wordpress.org/extend/themes/tarski"&gt;Tarski from the theme directory&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In all honesty, developing in &lt;abbr title="PHP: Hypertext Preprocessor"&gt;PHP&lt;/abbr&gt; with Subversion as my version control system is starting to feel very tedious. Fiddling with some WordPress hooks earlier today, I pondered how much easier it would be to do simple things if PHP had &lt;a href="http://www.joelonsoftware.com/items/2006/08/01.html"&gt;first-class functions&lt;/a&gt;. You could do something like this:&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;add_filter('the_content', function($content) {
  return '&amp;lt;div class="content"&amp;gt;' . $content . '&amp;lt;/div&amp;gt;';
});&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which, of course, looks a lot more like JavaScript than PHP, but despite the &lt;a href="http://realtech.burningbird.net/learning-javascript/basics/javascript-the-good-parts"&gt;bad parts&lt;/a&gt; I&amp;#8217;d much rather write JavaScript than PHP&amp;#8212;and, lately, have been.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/extralogical/~4/OLYjxBRHEx0" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://extralogical.net/2008/07/the-state-of-the-art/#comments" thr:count="5" />
		<link rel="replies" type="application/atom+xml" href="http://extralogical.net/2008/07/the-state-of-the-art/feed/" thr:count="5" />
		<thr:total>5</thr:total>
	<feedburner:origLink>http://extralogical.net/2008/07/the-state-of-the-art/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Benedict</name>
						<uri>http://extralogical.net</uri>
					</author>
		<title type="html"><![CDATA[No Smoking]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/extralogical/~3/4SQIeWzX2eg/" />
		<id>http://extralogical.net/2007/07/no-smoking/</id>
		<updated>2009-01-13T13:35:39Z</updated>
		<published>2007-07-28T21:57:36Z</published>
		<category scheme="http://extralogical.net" term="Uncategorised" /><category scheme="http://extralogical.net" term="childhood" /><category scheme="http://extralogical.net" term="London" /><category scheme="http://extralogical.net" term="public transport" /><category scheme="http://extralogical.net" term="smoking" />		<summary type="html"><![CDATA[Public transport, smoking, and life in London.]]></summary>
		<content type="html" xml:base="http://extralogical.net/2007/07/no-smoking/">&lt;p&gt;At school we learned how to buy train tickets in French, and in the process discovered we needed to make an alien specification: &lt;em lang="fr-FR"&gt;fumeur ou non-fumeur&lt;/em&gt;? &lt;a href="http://en.wikipedia.org/wiki/British_Rail"&gt;British Rail&lt;/a&gt;&amp;#8212;at it may no longer have been by then, but as I still thought of it&amp;#8212;had outlawed smoking on its trains years before. Notices on every window reminded one with threats of sanctions.&lt;/p&gt;
&lt;p&gt;The maximum fine was £500, while on the buses it was £2000; a curious incongruity. After all, they were both grubby, unpretentious, overworked components of our public transport network. If anything, the train was a grander mode of transport&amp;#8212;and this, I thought, should have been reflected in the fines.&lt;/p&gt;
&lt;p&gt;Transport was the prism through which I encountered the world&amp;#8212;a world on the move. People stared distractedly at their newspapers or out of the window, attempting to transport their minds from their prosaic surroundings just as the train transported their body through drab suburbia, from Twickenham to Clapham Junction and thence into the city. Rusting gas holders, blackened bridges, concrete tower blocks and horrid bungalows all flowed past as we clattered towards Waterloo. Occasionally one would catch a whiff of illicit cigarette smoke&amp;#8212;but not often.&lt;/p&gt;
&lt;p&gt;Now smoking has departed that other bastion of public life: the pub. The smokers have been kicked out, just as they were from the buses and trains. But unlike the proletarian local rail and bus networks, where there are no First Class carriages and everyone rides together, pubs and bars exhibit the same stratification as society. Barring undesirables is easy&amp;#8212;just price them out. If they can&amp;#8217;t afford three-fifty a pint, then by definition they&amp;#8217;re the wrong sort.&lt;/p&gt;
&lt;p&gt;London is too much in my blood to spurn it easily, but some grey days the grime and money and poverty&amp;#8212;and the attitudes they bring with them&amp;#8212;just grind me down. Between themselves, Londoners do nothing but moan about their city; put them in a room with someone from anywhere else and they&amp;#8217;ll defend it to the death as the greatest in the world. Hardly surprising it didn&amp;#8217;t make Monocle&amp;#8217;s &lt;a href="http://www.monocle.com/Magazine/volume-01/issue-05/"&gt;top 20 liveable cities&lt;/a&gt;: ambivalence, for those with open eyes, is our defining attitude.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/extralogical/~4/4SQIeWzX2eg" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://extralogical.net/2007/07/no-smoking/#comments" thr:count="4" />
		<link rel="replies" type="application/atom+xml" href="http://extralogical.net/2007/07/no-smoking/feed/" thr:count="4" />
		<thr:total>4</thr:total>
	<feedburner:origLink>http://extralogical.net/2007/07/no-smoking/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Benedict</name>
						<uri>http://extralogical.net</uri>
					</author>
		<title type="html"><![CDATA[Detect Current Page Template]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/extralogical/~3/YsFj_Qm1yV8/" />
		<id>http://extralogical.net/2007/06/detect-template/</id>
		<updated>2009-01-13T13:35:39Z</updated>
		<published>2007-06-18T00:25:12Z</published>
		<category scheme="http://extralogical.net" term="Uncategorised" /><category scheme="http://extralogical.net" term="Tarski" /><category scheme="http://extralogical.net" term="WordPress" />		<summary type="html"><![CDATA[Detect the template in use by the current page---no <abbr title="Structured Query Language">SQL</abbr> required.]]></summary>
		<content type="html" xml:base="http://extralogical.net/2007/06/detect-template/">&lt;p&gt;On the back of my &lt;a href="http://extralogical.net/2007/06/wphooks/"&gt;hooks article&lt;/a&gt; last week, here&amp;#8217;s another potentially useful WordPress trick I&amp;#8217;ve picked up: detecting the current page template.&lt;/p&gt;
&lt;h3&gt;No SQL required&lt;/h3&gt;
&lt;p&gt;The beauty of the WordPress &lt;acronym title="Application Programming Interface"&gt;API&lt;/acronym&gt; is that in most situations, you can pull the values you need from the database without writing lines of &lt;acronym title="Structured Query Language"&gt;SQL&lt;/acronym&gt; code. For example,&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;global $post;
get_post_meta($post-&amp;gt;ID,'_wp_page_template',true);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This returns the template being used by the current page&amp;#8212;for example, running it on my &lt;a href="http://extralogical.net/archives/"&gt;archives page&lt;/a&gt; would return the value &lt;code&gt;archives.php&lt;/code&gt;, while doing it on my &lt;a href="http://extralogical.net/about/"&gt;about page&lt;/a&gt; would return &lt;code&gt;default&lt;/code&gt;. The function &lt;code&gt;get_post_meta&lt;/code&gt; is documented &lt;a href="http://codex.wordpress.org/Using_Custom_Fields#PostMeta_Functions"&gt;in the Codex&lt;/a&gt;, but basically, it grabs some data from the &lt;code&gt;wp_postmeta&lt;/code&gt; table of the database, which is used to store custom fields, including the post template.&lt;/p&gt;
&lt;h3&gt;A trip through &lt;code&gt;postmeta&lt;/code&gt; land&lt;/h3&gt;
&lt;p&gt;By using the WordPress-generated &lt;code&gt;$post&lt;/code&gt; variable, we avoid having to talk to &lt;a href="http://codex.wordpress.org/Database_Description"&gt;the database&lt;/a&gt; directly; &lt;code&gt;$post-&amp;gt;ID&lt;/code&gt; returns the &lt;code&gt;ID&lt;/code&gt; value of the current post, which can then be checked against &lt;a href="http://codex.wordpress.org/Database_Description#Table:_wp_postmeta"&gt;the records&lt;/a&gt; in &lt;code&gt;wp_postmeta&lt;/code&gt;. Since we want to return the page&amp;#8217;s template, our second argument calls the key &lt;code&gt;_wp_page_template&lt;/code&gt;, so the function will only return values with that key.&lt;/p&gt;
&lt;p&gt;By default, the function returns an array, but by setting the third argument to &lt;code&gt;true&lt;/code&gt; we can make it return a single result (the first one, although it&amp;#8217;s pretty unlikely that a page has two &lt;code&gt;_wp_page_template&lt;/code&gt; values. Obviously this technique can be extended to return the values for other custom fields, but I&amp;#8217;ll leave that as an exercise for the reader.&lt;/p&gt;
&lt;h3&gt;The why of it&lt;/h3&gt;
&lt;p&gt;This trick could be useful for any number of things&amp;#8212;I&amp;#8217;m using it in &lt;a href="http://tarskitheme.com/"&gt;Tarski&lt;/a&gt; to check whether a given page is an archives page, and to include or exclude certain things based on the result.&lt;/p&gt;
&lt;p&gt;Obviously if I were just doing the include directly in the archives template, this wouldn&amp;#8217;t be a problem, but since I&amp;#8217;m actually calling a &lt;a href="http://extralogical.net/2007/06/wphooks/"&gt;hook&lt;/a&gt; that&amp;#8217;s present in a number of other templates, there&amp;#8217;s no way I can tell in advance whether a given page is an archives page or not. In effect, I&amp;#8217;m putting the coding burden onto &lt;em&gt;my&lt;/em&gt; actions and filters, so as to not impose an overly restrictive system on end-users who might want to do something entirely different.&lt;/p&gt;
&lt;h3&gt;Coda&lt;/h3&gt;
&lt;p&gt;As a non-programmer myself, I&amp;#8217;m always trying to work out how to do fairly simple things in WordPress. If people are interested, I could carry on writing up these code tips, so let me know what you think in the comments.&lt;/p&gt;
&lt;h3&gt;Amendment, 5&lt;sup&gt;th&lt;/sup&gt; November 2007&lt;/h3&gt;
&lt;p&gt;If you&amp;#8217;re on the WordPress &lt;a href="http://svn.automattic.com/wordpress/trunk/"&gt;trunk&lt;/a&gt;, instead of bothering with all this malarky just use the &lt;code&gt;is_page_template&lt;/code&gt; function which was added in revision &lt;a href="http://trac.wordpress.org/changeset/6228"&gt;6228&lt;/a&gt;. It will be in the 2.4 release when that comes out, and it uses essentially the same technique as I&amp;#8217;ve described here, albeit with&amp;#8212;as you&amp;#8217;d expect&amp;#8212;much more complete error handling.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/extralogical/~4/YsFj_Qm1yV8" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://extralogical.net/2007/06/detect-template/#comments" thr:count="5" />
		<link rel="replies" type="application/atom+xml" href="http://extralogical.net/2007/06/detect-template/feed/" thr:count="5" />
		<thr:total>5</thr:total>
	<feedburner:origLink>http://extralogical.net/2007/06/detect-template/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Benedict</name>
						<uri>http://extralogical.net</uri>
					</author>
		<title type="html"><![CDATA[Adding Custom WordPress Hooks]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/extralogical/~3/CKHMi9Hx4Sw/" />
		<id>http://extralogical.net/2007/06/wphooks/</id>
		<updated>2009-01-13T13:35:39Z</updated>
		<published>2007-06-13T11:32:39Z</published>
		<category scheme="http://extralogical.net" term="Uncategorised" /><category scheme="http://extralogical.net" term="Tarski" /><category scheme="http://extralogical.net" term="WordPress" />		<summary type="html"><![CDATA[How to add custom <abbr title="Application Programming Interface">API</abbr> hooks to your WordPress theme.]]></summary>
		<content type="html" xml:base="http://extralogical.net/2007/06/wphooks/">&lt;p&gt;All theme authors should have a vague idea of what &lt;a href="http://codex.wordpress.org/Plugin_API#Hooks.2C_Actions_and_Filters"&gt;WordPress hooks&lt;/a&gt; are: those things you have to remember to add to your header to stop plugin authors yelling at you. More technically, they&amp;#8217;re a way of adding to or altering the content that WordPress outputs.&lt;/p&gt;
&lt;p&gt;There are a fair few &lt;a href="http://wphooks.flatearth.org/"&gt;built into WordPress&lt;/a&gt;, and a number need to be &lt;a href="http://codex.wordpress.org/Theme_Development#Plugin_API_Hooks"&gt;correctly implemented&lt;/a&gt; by theme authors, but I don&amp;#8217;t propose to go into that here. What I&amp;#8217;m going to run through in this article is how you can add your own actions and filters to your theme, to make it more flexible and customisable.&lt;/p&gt;
&lt;p&gt;Before I get started, a couple of notes on the WordPress development environment. Firstly, updates break things. When &lt;abbr title="WordPress"&gt;WP&lt;/abbr&gt; 2.1 came out we had to rewrite our &lt;abbr title="Structured Query Language"&gt;SQL&lt;/abbr&gt; code to work with the new database structure. 2.2 brought widgets into the core and the link in &lt;a href="http://tarskitheme.com/"&gt;Tarski&lt;/a&gt;&amp;#8217;s Options page (which was pointing to the widgets plugin page) no longer worked. For 2.3 we&amp;#8217;re going to have to strip out our &lt;abbr title="Ultimate Tag Warrior"&gt;UTW&lt;/abbr&gt; code and make the theme work with the new tagging system. In other words, &lt;em&gt;themes need to be kept updated&lt;/em&gt;, even though this will destroy any alteration of the theme&amp;#8217;s files. Themes should &lt;a href="http://extralogical.net/2006/05/the-nesting-instinct/"&gt;come with tools&lt;/a&gt; that allow customisation but don&amp;#8217;t require the alteration of core files. Users shouldn&amp;#8217;t be deterred from upgrading by the prospect of losing their tweaks&amp;#8212;which of course is why plugins exist.&lt;/p&gt;
&lt;h3&gt;Anatomy of a theme hook&lt;/h3&gt;
&lt;p&gt;There are &lt;a href="http://wphooks.flatearth.org/filter-vs-action/"&gt;two kinds of hooks&lt;/a&gt;: actions and filters. This article deals mainly with actions, since they&amp;#8217;re generally simpler, but all its lessons can be applied to filters without much difficulty.&lt;/p&gt;
&lt;p&gt;Theme hooks are just functions; &lt;code&gt;wp_head&lt;/code&gt; is a good example of one. It&amp;#8217;s defined in &lt;code&gt;wp-includes/general-template.php&lt;/code&gt;, and the definition is amazingly simple:&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;function wp_head() {
    do_action('wp_head');
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;do_action&lt;/code&gt; function that does the hard work, tying the &lt;code&gt;wp_head&lt;/code&gt; function into WordPress&amp;#8217;s hooks system. It&amp;#8217;s incredibly simple to add new hooks in the same way.&lt;/p&gt;
&lt;h3&gt;Adding custom hooks&lt;/h3&gt;
&lt;p&gt;There are three steps to adding a custom hook to a theme. Firstly, add the hook function. Secondly, add the action to your theme in the spot where you want it to be executed. Thirdly, you can add a function defining the default behaviour&amp;#8212;for example, if you were writing a hook for a header image, you&amp;#8217;d need to write something to display a header image. Lastly, tie the two together with &lt;code&gt;add_action&lt;/code&gt;. Note that the third and fourth steps are optional; your hook doesn&amp;#8217;t have to do anything by default.&lt;/p&gt;
&lt;p&gt;Since I&amp;#8217;ve been working on adding hooks to &lt;a href="http://tarskitheme.com/"&gt;Tarski&lt;/a&gt;, I&amp;#8217;ll use an example from there. Unless stated otherwise, this code is being added to the theme&amp;#8217;s &lt;code&gt;functions.php&lt;/code&gt; file which is automatically included by WordPress. Below is the action definition: it adds an action named &lt;code&gt;th_header&lt;/code&gt; to WordPress&amp;#8217;s hooks listing.&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;function th_header() {
    do_action('th_header');
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I then added the function call to the header template, so that whenever that template file is called it will do whatever actions have been added to the &lt;code&gt;th_header&lt;/code&gt; hook:&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;&amp;lt;?php th_header(); ?&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Originally I was just going to use this to add a header image, thinking that if people wanted to make their header image rotate randomly, or display page-specific headers, they could do that with a plugin. But then I realised I could use the same hook to also display the title and the tagline. To do this, I just reused the existing header image, site title and tagline functions, and then added these lines of code to make the hook call them:&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;add_action('th_header','tarski_headerimage',5);
add_action('th_header','tarski_sitetitle',6);
add_action('th_header','tarski_tagline',7);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that the first argument is the same for all three lines: &lt;code&gt;th_header&lt;/code&gt;. This is the hook to which the actions are being added. The second argument is the actions (which, of course, are just functions which we&amp;#8217;ve defined elsewhere). The third argument is the &lt;em&gt;priority&lt;/em&gt;&amp;#8212;the order in which the actions should be performed. This will make the header display first; then the title; then the tagline.&lt;/p&gt;
&lt;h3&gt;Tweaking with a plugin&lt;/h3&gt;
&lt;p&gt;Now the theme has its hooks, how does all this customisation work? It&amp;#8217;s very simple&amp;#8212;just &lt;a href="http://codex.wordpress.org/Writing_a_Plugin"&gt;write a plugin&lt;/a&gt;. This can be completely independent of the theme, so you can update the theme without fear of losing your tweaks (because they&amp;#8217;re all in the plugin). I don&amp;#8217;t propose to cover the basics of plugin development here; try &lt;a href="http://asymptomatic.net/2005/02/22/1328/how-to-write-a-simple-wordpress-plugin/"&gt;this tutorial&lt;/a&gt;, or &lt;a href="http://headzoo.com/tutorials/writing-a-wordpress-plugin"&gt;this one&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First things first: what do we want to do? Well, how about writing a little &amp;#8220;About this site&amp;#8221; blurb and adding it below the tagline? This is very easy: just add the function to output the blurb to your plugin, and then add an action to the requisite hook.&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;function output_about_text() {
    echo '&amp;lt;p&amp;gt;This site is amazing.&amp;lt;/p&amp;gt;';
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That does it for the text; how about the action?&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;add_action('th_header','output_about_text');&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that we didn&amp;#8217;t add a priority; this value defaults to 10, so the about text will be displayed after the tagline. If you want to add it before the header image, for example, try this:&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;add_action('th_header','output_about_text',4);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let&amp;#8217;s now turn to a more complex example: replacing the header image with page-specific headers. Again, just write the function:&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;function page_specific_headers() {
    if(is_home()) {
        echo '&amp;lt;img alt="Home" src="home-page-header.gif" /&amp;gt;';
    } elseif(is_page('about')) {
        echo '&amp;lt;img alt="About" src="about-page-header.gif" /&amp;gt;';
    } else {
        echo '&amp;lt;img alt="Header" src="general-header.gif" /&amp;gt;';
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then we need to do &lt;em&gt;two&lt;/em&gt; things: add the new action, and remove the default one.&lt;/p&gt;
&lt;pre lang="PHP"&gt;&lt;code&gt;remove_action('th_header','tarski_headerimage',5);
add_action('th_header','page_specific_headers',5);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This should remove the default header image, and replace it with the page-specific one. Note that the priority needs to be specified for both the action being removed (since it&amp;#8217;s set in the default action) and for the action being added (since we want the header to be displayed in the same place, before the title and tagline).&lt;/p&gt;
&lt;p&gt;Theme hooks in this mould will be a new feature in &lt;a href="http://tarskitheme.com/"&gt;Tarski&lt;/a&gt; 1.5. If you want to try them out in the meantime, just check out the latest build from our &lt;a href="http://tarskitheme.com/2007/04/15/tarski-subversion-respository/"&gt;Subversion repository&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://feeds.feedburner.com/~r/extralogical/~4/CKHMi9Hx4Sw" height="1" width="1"/&gt;</content>
		<link rel="replies" type="text/html" href="http://extralogical.net/2007/06/wphooks/#comments" thr:count="11" />
		<link rel="replies" type="application/atom+xml" href="http://extralogical.net/2007/06/wphooks/feed/" thr:count="11" />
		<thr:total>11</thr:total>
	<feedburner:origLink>http://extralogical.net/2007/06/wphooks/</feedburner:origLink></entry>
	</feed>

