<?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://www.samsarin.com/blog/wp-atom.php">
	<title type="text">Samsarin</title>
	<subtitle type="text">Chris Pettitt's Blog</subtitle>

	<updated>2009-06-20T19:19:46Z</updated>
	<generator uri="http://wordpress.org/" version="2.7">WordPress</generator>

	<link rel="alternate" type="text/html" href="http://www.samsarin.com/blog" />
	<id>http://www.samsarin.com/blog/feed/atom/</id>
	

			<link rel="self" href="http://feeds.feedburner.com/Samsarin" type="application/atom+xml" /><feedburner:emailServiceId>Samsarin</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><entry>
		<author>
			<name>Chris Pettitt</name>
						<uri>http://blog.samsarin.com</uri>
					</author>
		<title type="html"><![CDATA[Samsarin PHP Widget 2.0 Beta 1]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Samsarin/~3/fr6BJu09yWk/" />
		<id>http://www.samsarin.com/blog/?p=66</id>
		<updated>2009-06-20T19:19:46Z</updated>
		<published>2009-06-20T19:19:46Z</published>
		<category scheme="http://www.samsarin.com/blog" term="Plugin" /><category scheme="http://www.samsarin.com/blog" term="Wordpress" />		<summary type="html"><![CDATA[I&#8217;ve finished writing Samsarin PHP Widget 2.0 Beta 1, which is compatible with Wordpress 2.8. It is a complete rewrite, so I plan to leave it in a beta state for a few weeks while I get feedback. If you do try the beta, please let me know how it goes.

Two important considerations with this [...]]]></summary>
		<content type="html" xml:base="http://www.samsarin.com/blog/2009/06/20/samsarin-php-widget-20-beta-1/"><![CDATA[<p>I&#8217;ve finished writing <a href="http://downloads.wordpress.org/plugin/samsarin-php-widget.2.0b1.zip">Samsarin PHP Widget 2.0 Beta 1</a>, which is compatible with Wordpress 2.8. It is a complete rewrite, so I plan to leave it in a beta state for a few weeks while I get feedback. If you do try the beta, please let me know how it goes.</p>

<p>Two important considerations with this plugin:</p>

<ul>
<li>As this is a complete rewrite it is not compatible with older versions of Wordpress. Use the 1.3.2 plugin for older versions.</li>
<li>The plugin doesn&#8217;t upgrade old Samsarin PHP Widgets - it looks like I may be able to make upgrade possible, but it needs more investigation.</li>
</ul>
]]></content>
		<link rel="replies" type="text/html" href="http://www.samsarin.com/blog/2009/06/20/samsarin-php-widget-20-beta-1/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://www.samsarin.com/blog/2009/06/20/samsarin-php-widget-20-beta-1/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://www.samsarin.com/blog/2009/06/20/samsarin-php-widget-20-beta-1/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Chris Pettitt</name>
						<uri>http://blog.samsarin.com</uri>
					</author>
		<title type="html"><![CDATA[Quarantined Files in Leopard]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Samsarin/~3/tff9rmylJ9E/" />
		<id>http://www.samsarin.com/blog/?p=53</id>
		<updated>2009-02-27T03:43:38Z</updated>
		<published>2009-02-27T01:52:39Z</published>
		<category scheme="http://www.samsarin.com/blog" term="Mac OSX" /><category scheme="http://www.samsarin.com/blog" term="Webdesign" />		<summary type="html"><![CDATA[This short post will share some information I learned about quarantined files on Leopard and how I recursively removed my isolated files from quarantine.

Today I was working on a MacPort for RabbitMQ and noticed something odd when I tar&#8216;d up the package:

$ tar cvfz rabbitmq-server-macport-1.5.3.tar.gz net
./._net
net/
net/._rabbitmq-server
net/rabbitmq-server/
net/rabbitmq-server/._files
...


Initially I was really confused by the files ._net, ._rabbitmq-server, [...]]]></summary>
		<content type="html" xml:base="http://www.samsarin.com/blog/2009/02/26/quarantined-files-in-leopard/"><![CDATA[<p>This short post will share some information I learned about quarantined files on Leopard and how I recursively removed my isolated files from quarantine.</p>

<p>Today I was working on a <a href="http://www.macports.org/">MacPort</a> for <a href="http://www.rabbitmq.com/">RabbitMQ</a> and noticed something odd when I <code>tar</code>&#8216;d up the package:</p>

<pre><code>$ tar cvfz rabbitmq-server-macport-1.5.3.tar.gz net
./._net
net/
net/._rabbitmq-server
net/rabbitmq-server/
net/rabbitmq-server/._files
...
</code></pre>

<p>Initially I was really confused by the files <code>._net</code>, <code>._rabbitmq-server</code>, etc., because they did not exist in the directory. Finally I noticed something interesting about the <code>ls</code> output:</p>

<pre><code>$ ls -ld net
drwxr-xr-x@ 3 cpettitt  staff  102 Feb 24 22:35 net
</code></pre>

<p>The file had a special attribute (denoted by the <code>@</code>). A quick read of the <code>ls</code> manpage revealed that I could learn more about the <code>@</code> property with <code>ls -@</code>:</p>

<pre><code>$ ls -@ld net
drwxr-xr-x@ 3 cpettitt  staff  102 Feb 24 22:35 net
        com.apple.quarantine     42
</code></pre>

<p>Immediately I remembered that downloaded files are automatically quarantined by Leopard. It just so happens that I had download the package to test it and make changes. The files in the subdirectories of net were also quarantined, so I came up with a quick command to remove a tree of files from quarantine:</p>

<pre><code>$ find . -print0 | xargs -0 xattr -l | grep com.apple.quarantine | 
         cut -d: -f1 | xargs -I% xattr -d com.apple.quarantine %
</code></pre>

<p>This command searches for all files starting from the root directory (<code>.</code>) and sends them to xargs. I used <code>-print0</code> and <code>-0</code> so that xargs handled files with whitespace correctly.</p>

<p>The <code>xattr -l</code> command lists all extended  attributes for the file and the subsequent <code>grep</code> filters out all files but those that are quarantined. The <code>cut</code> pattern just pulls the filename from what appears to be a colon (<code>:</code>) separated list.</p>

<p>Finally I tell <code>xattr</code> to delete the quarantine attribute. I used the <code>-I</code> option to set up a replacement for <code>%</code> because it also forces xargs to only split on newlines and not all whitespace (including spaces in filenames).</p>

<p>Having freed my files, tar worked as I expected:</p>

<pre><code>$ !tar
tar cvfz rabbitmq-server-macport-1.5.3.tar.gz net
net/
net/rabbitmq-server/
net/rabbitmq-server/files/
net/rabbitmq-server/files/rabbitmqctl_wrapper
net/rabbitmq-server/Portfile
</code></pre>

<p>Hopefully this will save someone else some time!</p>
]]></content>
		<link rel="replies" type="text/html" href="http://www.samsarin.com/blog/2009/02/26/quarantined-files-in-leopard/#comments" thr:count="0" />
		<link rel="replies" type="application/atom+xml" href="http://www.samsarin.com/blog/2009/02/26/quarantined-files-in-leopard/feed/atom/" thr:count="0" />
		<thr:total>0</thr:total>
	<feedburner:origLink>http://www.samsarin.com/blog/2009/02/26/quarantined-files-in-leopard/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Chris Pettitt</name>
						<uri>http://blog.samsarin.com</uri>
					</author>
		<title type="html"><![CDATA[Copying the GNU screen buffer to the Leopard clipboard]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Samsarin/~3/17X35qkTwUs/" />
		<id>http://www.samsarin.com/blog/?p=40</id>
		<updated>2008-10-18T16:25:00Z</updated>
		<published>2008-10-18T16:13:58Z</published>
		<category scheme="http://www.samsarin.com/blog" term="Mac OSX" />		<summary type="html"><![CDATA[Quite a while back I wrote an article about how I use GNU screen&#8217;s scrollback buffer. In the article I detailed how to copy the scrollback buffer into the Mac clipboard, which made it easy to copy data to other Mac applications. Unfortunately, I recently moved to Leopard and discovered this no longer works. In [...]]]></summary>
		<content type="html" xml:base="http://www.samsarin.com/blog/2008/10/18/copying-gnu-screen-buffer-to-leopard-clipboard/"><![CDATA[<p>Quite a while back I wrote an article about how I use <a href="http://www.samsarin.com/blog/2007/03/11/gnu-screen-working-with-the-scrollback-buffer/">GNU screen&#8217;s scrollback buffer</a>. In the article I detailed how to copy the scrollback buffer into the Mac clipboard, which made it easy to copy data to other Mac applications. Unfortunately, I recently moved to Leopard and discovered this no longer works. In this short article I will explain an updated procedure that works for Leopard.</p>

<p><span id="more-40"></span></p>

<h2>The Problem</h2>

<p>In Leopard, both pbcopy and pbpaste appear to crash when run from GNU screen. I did some basic investigation and found that pbcopy and pbpaste work by talking to a daemon called pboard, which is managed by launchd in Leopard. Any subprocess launched by GNU screen  seems to be unable to talk to pboard, though pbcopy does work with a pboard instance launched from within screen. Unfortunately this defeats the purpose because the pboard instance launched in screen does not work with the OS.</p>

<p>I was not successful in uncovering the reason that pbcopy in screen can&#8217;t talk to the pboard process started by launchd. If anyone knows why this is the case I would be very, very happy to hear about it.</p>

<h2>My Solution</h2>

<p>I realized that if I could somehow get pbcopy running in screen to talk to the pboard running outside of screen then I could write to the Leopard clipboard from screen. The solution I came up with is to start a process outside of screen that listens on a UNIX domain socket. When it receives a message it copies it to the Leopard clipboard using pbcopy. Within screen I use a client that pushes screen&#8217;s /tmp/screen-exchange file over the UNIX domain socket.</p>

<p>Here are the scripts:</p>

<ul>
<li><a href="http://www.samsarin.com/blog/files/uploads/2008/10/pboard_server">pboard_server</a></li>
<li><a href="http://www.samsarin.com/blog/files/uploads/2008/10/pboard_client">pboard_client</a></li>
</ul>

<p>You will need to <code>chmod 755 pboard_server pboard_client</code> after downloading them. To use the new pboard client, add the following to your <code>.screenrc</code>:</p>

<pre><code>bind b eval "writebuf" "exec ruby pboard_client"
</code></pre>

<p>If you used my previous tutorial, the line above should replace the old <code>bind b ...</code> line.</p>

<p>Now when you open a terminal (outside of screen), run <code>pboard_server &amp;</code>. This will start the process that listens for requests over the socket. You only need to do this once when you login, and you could automate this using launchd or some shell scripting from your .bashrc.</p>

<p>You should now be able to start screen and copy to the clipboard!</p>
]]></content>
		<link rel="replies" type="text/html" href="http://www.samsarin.com/blog/2008/10/18/copying-gnu-screen-buffer-to-leopard-clipboard/#comments" thr:count="8" />
		<link rel="replies" type="application/atom+xml" href="http://www.samsarin.com/blog/2008/10/18/copying-gnu-screen-buffer-to-leopard-clipboard/feed/atom/" thr:count="8" />
		<thr:total>8</thr:total>
	<feedburner:origLink>http://www.samsarin.com/blog/2008/10/18/copying-gnu-screen-buffer-to-leopard-clipboard/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Chris Pettitt</name>
						<uri>http://blog.samsarin.com</uri>
					</author>
		<title type="html"><![CDATA[Iterating Sparse Arrays in Lua 5.1]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Samsarin/~3/aLn5ynGI3lc/" />
		<id>http://www.samsarin.com/blog/?p=38</id>
		<updated>2008-06-10T16:50:05Z</updated>
		<published>2008-05-30T22:46:04Z</published>
		<category scheme="http://www.samsarin.com/blog" term="Lua" />		<summary type="html"><![CDATA[The Lua programming language is a scripting language that is light-weight (in terms of both syntax and size), fast, and easily embedded. I won&#8217;t spend a lot of time introducing Lua here (though I may do that in another article). If you haven&#8217;t used it, but you&#8217;re interested in getting started, a good place to [...]]]></summary>
		<content type="html" xml:base="http://www.samsarin.com/blog/2008/05/30/iterating-sparse-arrays-in-lua-51/"><![CDATA[<p>The <a href="http://www.lua.org/">Lua programming language</a> is a scripting language that is light-weight (in terms of both syntax and size), fast, and easily embedded. I won&#8217;t spend a lot of time introducing Lua here (though I may do that in another article). If you haven&#8217;t used it, but you&#8217;re interested in getting started, a good place to look is the well-written <a href="http://www.lua.org/docs.html">Lua documentation</a>.</p>

<p>I&#8217;m currently writing a library of higher-order functions in Lua called <a href="http://www.samsarin.com/blog/lua-functional/">lua-functional</a>. One of the early challenges was how to allow iteration over sparse arrays. Out of the box, Lua doesn&#8217;t stops iteration after reaching the first <code>nil</code> value. This article explores a two possible solutions to this problem and their consequences.</p>

<p><span id="more-38"></span></p>

<h3>Tables</h3>

<p><a href="http://www.lua.org/pil/2.5.html">Tables</a>, generally known as associative arrays, are the basis for all <a href="http://www.lua.org/pil/11.html">data structures</a> in Lua. A table in Lua looks like:</p>

<pre><code>my_table = { a = 1, b = 2, b = 3 }
</code></pre>

<h3>Arrays</h3>

<p>Lua also provides support for treating tables as non-associative arrays, as in:</p>

<pre><code>my_array = { 'value1', 'value2', 'value3' }
</code></pre>

<p>Internally Lua makes a table with this structure:</p>

<pre><code>my_array = { [1] = 'value1', [2] = 'value2', [3] = 'value3' }
</code></pre>

<p>such that</p>

<pre><code>for i, v in ipairs(my_array) do
    print(i .. " " .. v)
end
</code></pre>

<p>will print</p>

<pre><code>1 value1
2 value2
3 value3
</code></pre>

<p>The <a href="http://www.lua.org/manual/5.1/manual.html#pdf-ipairs">ipairs</a> function allows a table to be iterated over as an array. It returns the index (<code>i</code> above) and the value (<code>v</code> above). In Lua <code>..</code> is the string concatenation operator.</p>

<p>You may have noticed that the indices started at 1. That was intentional - it&#8217;s just the way Lua works.</p>

<h3>Sparse Arrays</h3>

<p>A sparse array is easy to create in Lua:</p>

<pre><code>my_array = { 'value1', [1000] = 'value1000' }
</code></pre>

<p>Unfortunately, iteration doesn&#8217;t work with it. Using <code>ipairs</code> like this:</p>

<pre><code>for i, v in ipairs(my_array) do
    print(k .. " " .. v)
end
</code></pre>

<p>will print</p>

<pre><code>1 value1
</code></pre>

<p>As soon as <code>ipairs</code> reaches a <code>nil</code> value (at index 2 in this case) it assumes it has reached the end of the array and stops.</p>

<h3>Solution 1: Creating a Custom Array Constructor with Metatables</h3>

<p>One obvious approach to solving this problem would be to write a custom array constructor using Lua&#8217;s <a href="http://www.lua.org/pil/13.html">metatables</a>. The following code uses a constructor, <code>new_array</code>, to return a custom array with a metatable that intercepts every table update:</p>

<pre><code>local array_mt = {
    __newindex = function(t, k, v)
        if type(k) == "number" and k &gt; t.n then rawset(t, 'n', k) end
        rawset(t, k, v)
    end
}

function new_array()
    arr = { n = 0 }
    setmetatable(arr, array_mt)
    return arr
end
</code></pre>

<p><a href="http://www.lua.org/pil/13.4.2.html">__newindex</a> is called each time code attempts to set a value on the table to which it is applied. Here it checks to see if the index, <code>k</code>, is greater than the largest index it knows, <code>n</code>, and if so it uses <code>rawset</code> to update the value of <code>n</code>.</p>

<p>The <code>new_array</code> function creates the new array, sets <code>n</code> to 0, and applies the custom metatable.</p>

<p>Next, we need a custom iterator that uses <code>array.n</code> to determine the end of the array, not the first <code>nil</code> value. Creating iterators in Lua is simple:</p>

<pre><code>function nipairs_custom_array(arr)
    if not arr.n then
        error("The given array was not creaated with new_array()", 2)
    end

    return function(arr, i)
        i = i + 1
        if i &lt;= arr.n then
            return i, a[i]
        end
    end, arr, 0
end
</code></pre>

<p>This code first checks to see if the given array was created by the <code>new_array</code> constructor. If it was, then it returns a <a href="http://www.lua.org/pil/6.1.html">closure</a> which iterates over each index while <code>i &lt;= arr.n</code>, the array to iterator over (which is passed to the function on each iteration), and the starting index (which is also passed to the function on each iteration). See <a href="http://www.lua.org/pil/7.html#GenericFor">generic for</a> for more information about how iterators work.</p>

<p>Finally, we need some code to test the performance of this iterator. I used the following code, which creates a new array with two values, one at index 1 and one at index 50,000,000. It prints the first and last value and then terminates.</p>

<pre><code>function test_mt(size)
    a = new_array()
    a[1] = 'beginning'
    a[size] = 'ending'

    for k, v in nipairs_custom_array(a) do
        if v then print(k, v) end
    end
end

test_my(50 * 1000 * 1000)
</code></pre>

<p>On my iMac with a Core2 Duo processor, I get the following results:</p>

<pre><code>$ time lua test1.lua
1       beginning
50000000        ending

real    0m17.039s
user    0m16.567s
sys     0m0.436s
</code></pre>

<p>I don&#8217;t like this solution. As an API developer, I don&#8217;t want to force users to use a custom array implementation. What do they do if they get an array from another library?</p>

<h3>Solution 2: Use the Iterator from Lua-functional</h3>

<p>Yes, I&#8217;m plugging a custom iterator I wrote for <a href="http://www.samsarin.com/blog/lua-functional/">lua-functional</a>. First, I&#8217;ll show you the performance results to compare with those above:</p>

<pre><code>$ time lua test2.lua
1       beginning
50000000        ending

real    0m12.809s
user    0m12.436s
sys     0m0.345s
</code></pre>

<p>The above results came from using the <code>nipairs</code> iterator, which is included in <a href="http://www.samsarin.com/blog/lua-functional/">lua-functional</a>. Here&#8217;s the current implementation:</p>

<pre><code>-- Defined in 'functional' module
function nipairs(arr)
    require_type(arr, "table")
    local upper = table.maxn(arr)
    return function(a, i)
        i = i + 1
        if i &lt;= upper then
            return i, a[i]
        end
    end, arr, 0
end
</code></pre>

<p>And here&#8217;s the code to run the test:</p>

<pre><code>function test_functional(size)
    a = { 'beginning', [size] = 'ending' }

    for k, v in functional.nipairs(a) do
        if v then print(k, v) end
    end
end

test_functional(50 * 1000 * 1000)
</code></pre>

<p>The first thing to note is that client code can use an ordinary array with this iterator. This is really key for me in designing the API. Clients do not need to use special arrays with this iterator.</p>

<p>The second thing to note is that instead of use a field on the table (<code>arr.n</code> in the last example), I use a local variable <code>upper</code> and access it through the function, which is acting as a closure. <code>table.maxn(arr)</code>, part of the standard Lua library, does a linear search through the table of the maximum index. This is unfortunate, but at least the performance of the whole operation is still <code>O(n)</code>.</p>

<p>You may have noticed that the performance of this iterator is counter-intuitively much better than that of the previous implementation. In Lua, access to a field from a closure is less expensive than accessing a field from a table. Likely, caching the value of <code>arr.n</code> above would have yielded better performance.</p>

<h3>Comparison to Explicit Iteration</h3>

<p>Just for the sake of comparison, I thought I would see how Lua performed if we were some how able to know the upper bound of a sparse array. Here is the code:</p>

<pre><code>function test_explicit(size)
    a = { 'beginning', [size] = 'ending' }

    for k = 1, size do
        v = a[k]
        if v then print(k, v) end
    end
end

test_explicit(50 * 1000 * 1000)
</code></pre>

<p>And the result:</p>

<pre><code>$ time lua test3.lua
1       beginning
50000000        ending

real    0m11.752s
user    0m11.420s
sys     0m0.303s
</code></pre>

<p>The result demonstrates that there is a cost associated with my solution. However, it is the best I&#8217;ve yet found as we do not know the upper bound of the array.</p>

<h3>Ruby Comparison</h3>

<p>One key factor in my decision to learn Lua was performance. I&#8217;d written a genetical algorithm framework in Ruby, but as it is computationally expensive, I thought Lua might be better suited to the challenge. I have yet to write the framework in Lua, but I thought I would test Ruby&#8217;s performance on a sparse array for comparison.</p>

<p>Here&#8217;s the Ruby code:</p>

<pre><code>size = 50 * 1000 * 1000
a = { 1 =&gt; 'beginning', size =&gt; 'ending' }
1.upto(size) { |i| v = a[i]; puts(i.to_s + " " + v) if v }
</code></pre>

<p>And here are the results:</p>

<pre><code>$ time ruby test4.rb
1 beginning
50000000 ending

real    0m28.177s
user    0m27.373s
sys     0m0.740s
</code></pre>

<p>Lua is 2.5 times faster in an apples-to-apples comparison and my implementation of nipairs is well over 2 times faster than the more optimal Ruby implementation.</p>

<h3>Final Notes</h3>

<p>I hope this article has given you some tools to consider when working with sparse arrays in Lua. It has touched on a number of interesting features of Lua, including iterators, closures, and metatables. Given enough interest, I will spend more time talking about these topics in upcoming articles.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://www.samsarin.com/blog/2008/05/30/iterating-sparse-arrays-in-lua-51/#comments" thr:count="3" />
		<link rel="replies" type="application/atom+xml" href="http://www.samsarin.com/blog/2008/05/30/iterating-sparse-arrays-in-lua-51/feed/atom/" thr:count="3" />
		<thr:total>3</thr:total>
	<feedburner:origLink>http://www.samsarin.com/blog/2008/05/30/iterating-sparse-arrays-in-lua-51/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Chris Pettitt</name>
						<uri>http://blog.samsarin.com</uri>
					</author>
		<title type="html"><![CDATA[Samsarin PHP Widget 1.3.2]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Samsarin/~3/vCVR1xX5ikY/" />
		<id>http://blog.samsarin.com/?p=20</id>
		<updated>2008-05-17T00:35:57Z</updated>
		<published>2008-05-14T02:55:03Z</published>
		<category scheme="http://www.samsarin.com/blog" term="Plugin" /><category scheme="http://www.samsarin.com/blog" term="Wordpress" />		<summary type="html"><![CDATA[I&#8217;ve just posted the latest update to the Samsarin PHP Widget. This version adds the ability to clear out the contents of one or all widgets with the click of a button. It  was also qualified with Wordpress 2.5.1 in Firefox, Safari, and Internet Explorer.

Thanks go to Kris for help in testing this feature.
]]></summary>
		<content type="html" xml:base="http://www.samsarin.com/blog/2008/05/13/samsarin-php-widget-132/"><![CDATA[<p>I&#8217;ve just posted the latest update to the <a href="/samsarin-php-widget">Samsarin PHP Widget</a>. This version adds the ability to clear out the contents of one or all widgets with the click of a button. It  was also qualified with Wordpress 2.5.1 in Firefox, Safari, and Internet Explorer.</p>

<p>Thanks go to <a href="http://blog.samsarin.com/2007/07/02/samsarin-php-widget-12/#comment-294">Kris</a> for help in testing this feature.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://www.samsarin.com/blog/2008/05/13/samsarin-php-widget-132/#comments" thr:count="1" />
		<link rel="replies" type="application/atom+xml" href="http://www.samsarin.com/blog/2008/05/13/samsarin-php-widget-132/feed/atom/" thr:count="1" />
		<thr:total>1</thr:total>
	<feedburner:origLink>http://www.samsarin.com/blog/2008/05/13/samsarin-php-widget-132/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Chris Pettitt</name>
						<uri>http://blog.samsarin.com</uri>
					</author>
		<title type="html"><![CDATA[Cool learning software: Mnemosyne]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Samsarin/~3/meCTw7561Xk/" />
		<id>http://blog.samsarin.com/2008/05/05/cool-learning-software-mnemosyne/</id>
		<updated>2008-06-08T15:33:46Z</updated>
		<published>2008-05-06T01:28:41Z</published>
		<category scheme="http://www.samsarin.com/blog" term="Learning" /><category scheme="http://www.samsarin.com/blog" term="Mac OSX" /><category scheme="http://www.samsarin.com/blog" term="Open Source" />		<summary type="html"><![CDATA[A couple weeks ago I came across an article about learning through spaced-repetition. The article claims that when you first learn something new you will tend to forget it rather quickly, but if you recall it at an optimal time (near when you would forget it) you will remember it for an even longer interval. [...]]]></summary>
		<content type="html" xml:base="http://www.samsarin.com/blog/2008/05/05/cool-learning-software-mnemosyne/"><![CDATA[<p>A couple weeks ago I came across an article about <a href="http://www.wired.com/medtech/health/magazine/16-05/ff_wozniak">learning through spaced-repetition</a>. The article claims that when you first learn something new you will tend to forget it rather quickly, but if you recall it at an optimal time (near when you would forget it) you will remember it for an even longer interval. As you continue to recall this information at these critical points the interval grows longer and longer, until it is measured in years. The article refers to software called SuperMemo, which can be purchased for the Windows operating system, but is not available for OSX, which I happen to use.</p>

<p>The idea of spaced-repetition was interesting enough for me to experiment. Initially I thought I might be stuck writing my own software, but fortunately I came across a very cool open source project called <a href="http://www.mnemosyne-proj.org/">Mnemosyne</a>, which works similarly to SuperMemo: it uses flash cards that quiz you on a piece of knowledge at critical times determined by its algorithm. Here&#8217;s an example of one of the cards in my system (from the <a href="http://www.mnemosyne-proj.org/node/55">European geography card deck</a>):</p>

<p><img class="centered" src='http://www.samsarin.com/blog/files/uploads/2008/05/mnemosyne-question.jpg' alt='Mnemosyne Screenshot' /></p>

<p>Cards can include graphics, sounds, or text. You can import card decks or you can create your own. I&#8217;ve been using it for about about two weeks to study European geography and Spanish (in combination with <a href="http://www.livemocha.com/">LiveMocha</a>). So far, I&#8217;ve found the system to be very helpful with both subjects, so I will continue the experiment. If you&#8217;re interested in learning a new subject, I would definitely recommend taking a look at this.</p>

<p><span id="more-13"></span></p>

<h3>Using MacPorts to Install Mnemosyne</h3>

<p>On OSX, Mnemosyne can be installed by downloading all of the dependencies and building from source or by using Fink (<a href="http://www.mnemosyne-proj.org/help/compiling-mac-os-x-1.php">instructions here</a>). I prefer MacPorts, and though it is not yet part of the port collection (I&#8217;m working on that), I have steps here that have been tested on OSX Tiger:</p>

<ol>
   <li>Install MacPorts</li>
   <li>Create a <a href="http://guide.macports.org/#development.local-repositories">local ports repository</a></li>
   <li>In your ports repository, create a new directory <code>education/mnemosyne</code></li>
   <li>Download the Mnemosyne <a href="https://trac.macosforge.org/projects/macports/attachment/ticket/15189/Portfile">Portfile</a> and put it in <code>education/mnemosyne</code>.</li>
   <li>Download a <a href="https://trac.macosforge.org/projects/macports/attachment/ticket/15189/patch-setup.py">patch for setup.py</a> and place it in <code>education/mnemosyne/files</code>.</li>
   <li>Update your port index by going to the root of your local repository and running <code>portindex</code>.</li>
   <li>Install the port by running: <code>sudo port install mnemosyne</code>.</li>
  </ol>

<h3>Running Mnemosyne on a USB Drive</h3>

<p>As I use both a laptop and a desktop, I want to keep my learning information in one place. The Mnemosyne website has a <a href="http://www.mnemosyne-proj.org/help/running-from-usb-drive.php">guide to use a USB drive</a>. However, I didn&#8217;t want to put the whole Mnemosyne package on my USB stick, just the data. Here&#8217;s my approach:</p>

<ol>
<li>Mount your USB stick (mine mounts to /Volumes/THUMBDRIVE)</li>
<li>Move your mnemosyne data to the USB stick: <code>mv ~/.mnemosyne /Volumes/THUMBDRIVE/mnemosyne</code></li>
<li>Symlink the mnemosyne data dir to the USB stick: <code>ln -s /Volumes/THUMBDRIVE/mnemosyne ~/.mnemosyne</code></li>
</ol>
]]></content>
		<link rel="replies" type="text/html" href="http://www.samsarin.com/blog/2008/05/05/cool-learning-software-mnemosyne/#comments" thr:count="12" />
		<link rel="replies" type="application/atom+xml" href="http://www.samsarin.com/blog/2008/05/05/cool-learning-software-mnemosyne/feed/atom/" thr:count="12" />
		<thr:total>12</thr:total>
	<feedburner:origLink>http://www.samsarin.com/blog/2008/05/05/cool-learning-software-mnemosyne/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Chris Pettitt</name>
						<uri>http://blog.samsarin.com</uri>
					</author>
		<title type="html"><![CDATA[Samsarin PHP Widget 1.2]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Samsarin/~3/gQarLLNzPqw/" />
		<id>http://samsarin.com/2007/07/02/samsarin-php-widget-12/</id>
		<updated>2008-05-17T00:37:30Z</updated>
		<published>2007-07-03T00:37:31Z</published>
		<category scheme="http://www.samsarin.com/blog" term="Plugin" /><category scheme="http://www.samsarin.com/blog" term="Wordpress" />		<summary type="html"><![CDATA[This new version of Samsarin PHP Widget increases the number of widgets available from 9 to 25. Enjoy!
]]></summary>
		<content type="html" xml:base="http://www.samsarin.com/blog/2007/07/02/samsarin-php-widget-12/"><![CDATA[<p>This new version of <a href="http://samsarin.com/samsarin-php-widget">Samsarin PHP Widget</a> increases the number of widgets available from 9 to 25. Enjoy!</p>
]]></content>
		<link rel="replies" type="text/html" href="http://www.samsarin.com/blog/2007/07/02/samsarin-php-widget-12/#comments" thr:count="29" />
		<link rel="replies" type="application/atom+xml" href="http://www.samsarin.com/blog/2007/07/02/samsarin-php-widget-12/feed/atom/" thr:count="29" />
		<thr:total>29</thr:total>
	<feedburner:origLink>http://www.samsarin.com/blog/2007/07/02/samsarin-php-widget-12/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Chris Pettitt</name>
						<uri>http://blog.samsarin.com</uri>
					</author>
		<title type="html"><![CDATA[Samsarin PHP Widget 1.1]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Samsarin/~3/Abwbplu3pnI/" />
		<id>http://samsarin.com/2007/05/21/8/</id>
		<updated>2008-05-17T00:38:03Z</updated>
		<published>2007-05-21T14:04:57Z</published>
		<category scheme="http://www.samsarin.com/blog" term="Plugin" /><category scheme="http://www.samsarin.com/blog" term="Wordpress" />		<summary type="html"><![CDATA[I&#8217;ve just posted Samsarin PHP Widget 1.1. If you are using Wordpress 2.2, please upgrade to this version. Wordpress 2.2 introduced an incompatibility in the widget library, which this new version addresses. Thanks to JR and Kathryn for posting comments and helping me locate this issue.
]]></summary>
		<content type="html" xml:base="http://www.samsarin.com/blog/2007/05/21/8/"><![CDATA[<p>I&#8217;ve just posted <a href="http://samsarin.com/samsarin-php-widget">Samsarin PHP Widget 1.1</a>. If you are using Wordpress 2.2, please upgrade to this version. Wordpress 2.2 introduced an incompatibility in the widget library, which this new version addresses. Thanks to JR and Kathryn for posting comments and helping me locate this issue.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://www.samsarin.com/blog/2007/05/21/8/#comments" thr:count="11" />
		<link rel="replies" type="application/atom+xml" href="http://www.samsarin.com/blog/2007/05/21/8/feed/atom/" thr:count="11" />
		<thr:total>11</thr:total>
	<feedburner:origLink>http://www.samsarin.com/blog/2007/05/21/8/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Chris Pettitt</name>
						<uri>http://blog.samsarin.com</uri>
					</author>
		<title type="html"><![CDATA[GNU Screen: Working with the Scrollback Buffer]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Samsarin/~3/QQ4TWGhJkCo/" />
		<id>http://samsarin.com/2007/03/11/gnu-screen-working-with-the-scrollback-buffer/</id>
		<updated>2008-05-11T04:47:18Z</updated>
		<published>2007-03-11T21:59:04Z</published>
		<category scheme="http://www.samsarin.com/blog" term="*nix" /><category scheme="http://www.samsarin.com/blog" term="Mac OSX" />		<summary type="html"><![CDATA[GNU Screen is a UNIX tool that allows multiple console applications to be run, each in its own &#8220;window&#8221;, from the same terminal. In a single Screen session, you can run interactive shells, mail programs, SSH sessions, and other console based applications, and you can easily switch between these using hotkeys. You can even split [...]]]></summary>
		<content type="html" xml:base="http://www.samsarin.com/blog/2007/03/11/gnu-screen-working-with-the-scrollback-buffer/"><![CDATA[<p><a href="http://www.gnu.org/software/screen/">GNU Screen</a> is a UNIX tool that allows multiple console applications to be run, each in its own &#8220;window&#8221;, from the same terminal. In a single Screen session, you can run interactive shells, mail programs, SSH sessions, and other console based applications, and you can easily switch between these using hotkeys. You can even split up the Screen display so that multiple Screen windows can be viewed at the same time.</p>

<p>If you&#8217;ve never used Screen, but frequently use console applications, it is definitely a tool worth exploring. An <a href="http://www.kuro5hin.org/story/2004/3/9/16838/14935">introduction to Screen</a> can be found on the Kuro5hin website.</p>

<p>In this article I share my experience with one of my favorite screen features: its scrollback buffer. As you interact with a Screen window, Screen stores a configurable number of lines of history in its scrollback buffer. The scrollback buffer makes it easy to browse or even search through the history of your windows. In addition, it makes it easy to copy and paste any section of text from the history.</p>

<p><span id="more-7"></span></p>

<h3>Configuring the Scrollback Buffer</h3>

<p>By default, the scrollback buffer only keeps the last 100 lines of text, which is not enough for my typical interaction with Screen. I&#8217;ve found a setting of 5000 lines to be more than adequate for my usage. The number of scrollback lines can be configured in your <em>$HOME/.screenrc</em> file, by adding the following line:</p>

<pre>defscrollback 5000</pre>

<p>This sets the scrollback to 5000 lines.</p>

<p>You can also override this default value when starting screen using the <em>-h [num]</em> option, where <em>num</em> is the number of scrollback lines.</p>

<p>Finally, if you want to change the number of lines of scrollback for a single window, using the &#8220;scrollback&#8221; command. Hit <em>C-a (Ctrl-A) :</em> to go to the Screen command line and type <em>scrollback num</em>, where <em>num</em> is the number of scrollback lines.</p>

<p>You can check the number of scrollback lines in your window. Hit <em>C-a i</em> to display window information. You will see a status line with information similar to the following:</p>

<pre>(27,42)/(186,42)+20 +flow UTF-8 3(bash)</pre>

<p>In this case, my scrollback is 20 lines (it is displayed as +20 in the output above).</p>

<h3>Entering Scrollback Mode and Navigating</h3>

<p>To enter scrollback hit <em>C-a [</em>. A status line will indicate that you've entered copy mode. To exit scrollback mode, hit the <em>escape</em> button.</p>

<p>Navigating in scrollback mode will be pretty familiar to VI users. Here are some of the most common navigation keys (taken from the screen manpage):</p>

<pre>
h -    Move the cursor left by one character
j -    Move the cursor down by one line
k -    Move the cursor up by one line
l -    Move the cursor right by one character
0 -    Move to the beginning of the current line
$ -    Move to the end of the current line.
G -    Moves to the specified line 
       (defaults to the end of the buffer).
C-u -  Scrolls a half page up.
C-b -  Scrolls a full page up.
C-d -  Scrolls a half page down.
C-f -  Scrolls the full page down.
</pre>

<p>I often use the page up and page down commands to quickly scroll back through the window's history.</p>

<p>In addition to traditional navigation, Screen allows you to search the scrollback buffer using the following commands:</p>

<pre>
/ -    Search forward
? -    Search backward
</pre>

<p>Search is a very useful feature. For example, you could run a script and search for keywords in the output (such as Error), without having to redirect the output.</p>

<h3>Copy and Paste</h3>

<p>Scrollback mode is also know as copy mode and it allows you to copy any section of text into a copy buffer. To copy text, move the cursor to the start of the text you want to copy, hit <em>spacebar</em>, move the cursor to the end of the text you want to copy (Screen will highlight the text to be copied as you move), and again hit <em>spacebar</em>. Screen will indicate the number of characters copied into the copy buffer.</p>

<p>To paste text, simply hit <em>C-a ]</em>.</p>

<h3>Copying to the Mac Clipboard</h3>

<p>While copying and pasting in a terminal is very useful, I also find that I often want to copy some text from a terminal into my clipboard. This next tip will show you how to do this for Mac OSX, but I'm sure it can be easily modified to work with other operating systems.</p>

<p>Open <em>$HOME/.screenrc</em> and add the following line:</p>

<pre>bind b eval "writebuf" "exec sh -c 'pbcopy &lt; /tmp/screen-exchange'"</pre>

<p>This line tells Screen to write its copy buffer to a temporary file (defaults to <em>/tmp/screen-exchange</em>), and then sends that file to <em>pbcopy</em>, a Mac OSX utility that copies text into the Mac clipboard. In this case, I&#8217;ve bound the command to <em>C-a b</em>, but you can change to best suit your own environment.</p>

<h3>Conclusion</h3>

<p>This wraps up my review of Screen&#8217;s scrollback buffer. I hope this tutorial is useful, especially to those that frequently work in terminal windows.</p>

<p>Do you have interesting ways of using Screen&#8217;s scrollback buffer, or Screen in general?</p>
]]></content>
		<link rel="replies" type="text/html" href="http://www.samsarin.com/blog/2007/03/11/gnu-screen-working-with-the-scrollback-buffer/#comments" thr:count="27" />
		<link rel="replies" type="application/atom+xml" href="http://www.samsarin.com/blog/2007/03/11/gnu-screen-working-with-the-scrollback-buffer/feed/atom/" thr:count="27" />
		<thr:total>27</thr:total>
	<feedburner:origLink>http://www.samsarin.com/blog/2007/03/11/gnu-screen-working-with-the-scrollback-buffer/</feedburner:origLink></entry>
		<entry>
		<author>
			<name>Chris Pettitt</name>
						<uri>http://blog.samsarin.com</uri>
					</author>
		<title type="html"><![CDATA[Samsarin PHP Widget 1.0]]></title>
		<link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Samsarin/~3/YnVGbX4LqyU/" />
		<id>http://samsarin.com/2007/03/10/samsarin-php-widget-10/</id>
		<updated>2008-05-17T00:38:39Z</updated>
		<published>2007-03-11T04:09:02Z</published>
		<category scheme="http://www.samsarin.com/blog" term="Plugin" /><category scheme="http://www.samsarin.com/blog" term="Wordpress" />		<summary type="html"><![CDATA[I&#8217;ve received numerous requests for the Samsarin PHP Widget, so I am happy to announce that is now available here. This widget makes it easy to add PHP code into the sidebar while using Automattic&#8217;s Widget plugin.
]]></summary>
		<content type="html" xml:base="http://www.samsarin.com/blog/2007/03/10/samsarin-php-widget-10/"><![CDATA[<p>I&#8217;ve received numerous requests for the Samsarin PHP Widget, so I am happy to announce that is now available <a href="http://samsarin.com/samsarin-php-widget">here</a>. This widget makes it easy to add PHP code into the sidebar while using <a href="http://automattic.com/code/widgets">Automattic&#8217;s Widget plugin</a>.</p>
]]></content>
		<link rel="replies" type="text/html" href="http://www.samsarin.com/blog/2007/03/10/samsarin-php-widget-10/#comments" thr:count="7" />
		<link rel="replies" type="application/atom+xml" href="http://www.samsarin.com/blog/2007/03/10/samsarin-php-widget-10/feed/atom/" thr:count="7" />
		<thr:total>7</thr:total>
	<feedburner:origLink>http://www.samsarin.com/blog/2007/03/10/samsarin-php-widget-10/</feedburner:origLink></entry>
	</feed>
