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

<channel>
	<title>tlrobinson.net blog &#187; Command line</title>
	<atom:link href="http://tlrobinson.net/blog/category/command-line/feed/" rel="self" type="application/rss+xml" />
	<link>http://tlrobinson.net/blog</link>
	<description></description>
	<lastBuildDate>Mon, 06 Apr 2009 08:37:15 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>ropen: Remote &quot;open&quot; command for opening remote files locally on OS X</title>
		<link>http://tlrobinson.net/blog/2009/04/ropen-remote-open-command/</link>
		<comments>http://tlrobinson.net/blog/2009/04/ropen-remote-open-command/#comments</comments>
		<pubDate>Sun, 05 Apr 2009 04:40:15 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Command line]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=94</guid>
		<description><![CDATA[The Problem &#8212;&#8212;&#8212;&#8211; Most Mac OS X power users know about the ["open"](http://tuvix.apple.com/documentation/Darwin/Reference/ManPages/man1/open.1.html) command line tool which opens the files specified as arguments in their default (or a specified) OS X application. Additionally, many OS X text editors, such as &#8230; <a href="http://tlrobinson.net/blog/2009/04/ropen-remote-open-command/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The Problem<br />
&#8212;&#8212;&#8212;&#8211;</p>
<p>Most Mac OS X power users know about the ["open"](http://tuvix.apple.com/documentation/Darwin/Reference/ManPages/man1/open.1.html) command line tool which opens the files specified as arguments in their default (or a specified) OS X application. Additionally, many OS X text editors, such as TextMate (&#8220;mate&#8221;) and SubEthaEdit (&#8220;see&#8221;), come with command line tools which can be used to open files.</p>
<p>These are great when working locally, but obviously do no work remotely. Often when working on remote servers you end up using command line editors which you may not be as familiar with.</p>
<p>ropen&#8217;s Solution<br />
&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>The [ropen](http://github.com/tlrobinson/ropen) tool solves this problem using two simple shell scripts, which make use of MacFuse&#8217;s sshfs. You run the &#8220;ropen&#8221; program on your remote machine(s) when you want to open a remote file locally (this is equivalent to the OS X &#8220;open&#8221; command). The &#8220;ropend&#8221; daemon runs on your local OS X machine waiting for open requests, and the &#8220;ropen.php&#8221; PHP script proxies requests from ropen to ropend.</p>
<p>How it works<br />
&#8212;&#8212;&#8212;&#8212;</p>
<p>1. When ropen is executed it makes an HTTP request to ropen.php with the paths to be opened and application to open them with, if any, as well as the SSH user, host, and port of the remote machine.<br />
2. ropen.php stores this open request in a queue that is tied to ROPEN_SECRET via PHP&#8217;s sessions.<br />
3. ropend polls ropen.php every 1 second waiting for open requests. When it receives one it mounts the remote filesystem using sshfs (if it&#8217;s not already mounted) and opens the files or directories specified.</p>
<p>More information<br />
&#8212;&#8212;&#8212;&#8212;</p>
<p>See more information about ropen on the [ropen project page](http://github.com/tlrobinson/ropen).</p>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2009/04/ropen-remote-open-command/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Determining the absolute absolute path of a shell script</title>
		<link>http://tlrobinson.net/blog/2009/03/determining-the-absolute-absolute-path-of-a-shell-script/</link>
		<comments>http://tlrobinson.net/blog/2009/03/determining-the-absolute-absolute-path-of-a-shell-script/#comments</comments>
		<pubDate>Mon, 30 Mar 2009 15:04:24 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Command line]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=91</guid>
		<description><![CDATA[In the course of working on projects like server-side Objective-J, jack, and now narwhal, I&#8217;ve often had to write shell scripts that needed to know their location in the filesystem. Rather than hardcoding it, I prefer to infer it automatically &#8230; <a href="http://tlrobinson.net/blog/2009/03/determining-the-absolute-absolute-path-of-a-shell-script/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In the course of working on projects like server-side <a href="http://cappuccino.org">Objective-J</a>, <a href="http://jackjs.org">jack</a>, and now <a href="http://github.com/tlrobinson/narwhal">narwhal</a>, I&#8217;ve often had to write shell scripts that needed to know their location in the filesystem. Rather than hardcoding it, I prefer to infer it automatically at runtime. Unfortunately this isn&#8217;t as easy as you would expect.</p>
<p>If the script is invoked with an absolute path (&#8220;/foo/bar/baz&#8221;) or from your PATH (&#8220;baz&#8221;), then &#8220;$0&#8243; in the script will contain the absolute of the script (&#8220;/foo/bar/baz&#8221;). However, if it is invoked using a relative path (&#8220;./bar/baz&#8221; from &#8220;/foo&#8221;) then $0 will contain the relative path (&#8220;./bar/baz&#8221;). Furthermore, if the path to the script is actually a symbolic link, you&#8217;ll get the symlink&#8217;s path instead of the original.</p>
<p>Surprisingly, I couldn&#8217;t find a definitive solution that handles all these cases, so I took the various ones I did find and created one which I think handles all the cases I&#8217;m aware of:</p>
<p><script src="http://gist.github.com/87785.js"></script></p>
<p>If you don&#8217;t want to resolve the symlinks remove the second half.</p>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2009/03/determining-the-absolute-absolute-path-of-a-shell-script/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Open new Terminal tab in current directory (updated!)</title>
		<link>http://tlrobinson.net/blog/2008/10/open-new-terminal-tab/</link>
		<comments>http://tlrobinson.net/blog/2008/10/open-new-terminal-tab/#comments</comments>
		<pubDate>Thu, 23 Oct 2008 08:47:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Command line]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=68</guid>
		<description><![CDATA[This is an updated shell script / AppleScript for opening a new tab in your current directory (or the specified directory). The last version was for the pre-tabbed version of Terminal. #!/bin/sh - if [ $# -ne 1 ]; then &#8230; <a href="http://tlrobinson.net/blog/2008/10/open-new-terminal-tab/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is an updated shell script / AppleScript for opening a new <em>tab</em> in your current directory (or the specified directory). The <a href="http://tlrobinson.net/blog/2007/09/07/open-new-terminal-window-in-current-or-other-specified-directory/">last version</a> was for the pre-tabbed version of Terminal.</p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; "><span style="color:#236e25;">#!/bin/sh -<br />
</span><br />
<span style="color:#881350;">if</span> [ <span style="color:#c4620a;">$#</span> -ne <span style="color:#0000ff;">1</span> ]; <span style="color:#881350;">then</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;PATHDIR=<span style="color:#660088;">`pwd`</span><br />
<span style="color:#881350;">else</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;PATHDIR=<span style="color:#c4620a;">$1</span><br />
<span style="color:#881350;">fi</span></p>
<p>/usr/bin/osascript &lt;&lt;-EOF<br />
activate application <span style="color:#760f15;">&quot;Terminal&quot;</span><br />
tell application <span style="color:#760f15;">&quot;System Events&quot;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;keystroke <span style="color:#760f15;">&quot;t&quot;</span> using {<span style="color:#440088;">command</span> down}<br />
end tell<br />
tell application <span style="color:#760f15;">&quot;Terminal&quot;</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;repeat with win <span style="color:#881350;">in</span> windows<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span> get frontmost of win is <span style="color:#880088;">true</span> <span style="color:#881350;">then</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">do</span> script <span style="color:#760f15;">&quot;cd </span><span style="color:#c4620a;">$PATHDIR</span><span style="color:#760f15;">; clear&quot;</span> <span style="color:#881350;">in</span><span style="color:#003369;"> </span>(selected tab of win)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end <span style="color:#881350;">if</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end try<br />
&nbsp;&nbsp;&nbsp;&nbsp;end repeat<br />
end tell<br />
EOF
</div>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2008/10/open-new-terminal-tab/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Command line interpreter and REPL for JSCocoa</title>
		<link>http://tlrobinson.net/blog/2008/10/command-line-interpreter-and-repl-for-jscocoa/</link>
		<comments>http://tlrobinson.net/blog/2008/10/command-line-interpreter-and-repl-for-jscocoa/#comments</comments>
		<pubDate>Fri, 10 Oct 2008 10:08:07 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Command line]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Objective-C]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=55</guid>
		<description><![CDATA[A few months ago I started working on a JavaScript to Objective-C bridge. We had already implemented Objective-C in JavaScript, so I figured &#8220;why not?&#8221; Well, I never got very far, but thankfully Patrick Geiller apparently had the same idea &#8230; <a href="http://tlrobinson.net/blog/2008/10/command-line-interpreter-and-repl-for-jscocoa/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A few months ago I started working on a JavaScript to Objective-C bridge. We had already <a href="http://cappuccino.org">implemented Objective-C in JavaScript</a>, so I figured &#8220;why not?&#8221;</p>
<p>Well, I never got very far, but thankfully <a href="http://parmanoir.com/">Patrick Geiller</a> apparently had the same idea and actually executed it: He <a href="http://parmanoir.com/JSCocoa%2C_a_bridge_from_Javascript_to_Cocoa">announced</a> <a href="http://inexdo.com/JSCocoa">JSCocoa</a> today. It looks like it&#8217;s a solid bridge, about up to par with <a href="http://pyobjc.sourceforge.net/">PyObjC</a> and <a href="http://rubycocoa.sourceforge.net/">RubyCocoa</a>.</p>
<p>While the included GUI interface for trying out JSCocoa is nice, I prefer command line interfaces for my languages, so I ripped out the few lines of code from my original bridge and plugged in JSCocoa.</p>
<p><a href="http://github.com/tlrobinson/tlrobinson/tree/master/jscocoa">Code and build instructions on GitHub</a>.</p>
<p>It&#8217;s very bare bones at the moment: it will either read one or more file names from the command line arguments, or if no arguments are supplied it will present a no-frills REPL. Obviously line-editing, etc would be one of the next steps, but for now it works nicely with <a href="http://http://tlrobinson.net/blog/?p=32">rlwrap</a>.</p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; "><span style="color:#683821;">#import &lt;Foundation/Foundation.h&gt;<br />
#import &quot;JSCocoaController.h&quot;<br />
</span><br />
<span style="color:#881350;">void</span> <span style="color:#003369;">JSValuePrint</span>(JSContextRef, JSValueRef, JSValueRef *);</p>
<p><span style="color:#881350;">int</span> <span style="color:#003369;">main </span>(<span style="color:#881350;">int</span> argc, <span style="color:#881350;">const</span> <span style="color:#881350;">char</span> * argv[])<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;[[<span style="color:#400080;">NSAutoreleasePool</span> <span style="color:#ff0000;">alloc</span>] <span style="color:#6c0540;">init</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">id</span> c = [JSCocoaController <span style="color:#6c0540;">sharedController</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;JSGlobalContextRef ctx = [c <span style="color:#6c0540;">ctx</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(argc &gt; <span style="color:#0000ff;">1</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">for</span><span style="color:#003369;"> </span>(<span style="color:#881350;">int</span> i = <span style="color:#0000ff;">1</span>; i &lt; argc; i++)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[c <span style="color:#6c0540;">evalJSFile:</span>[<span style="color:#400080;">NSString</span> <span style="color:#6c0540;">stringWithFormat:</span><span style="color:#760f15;">@&quot;%s&quot;</span>, argv[i]]];<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">else</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">while</span><span style="color:#003369;"> </span>(<span style="color:#0000ff;">1</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">char</span> buffer[<span style="color:#0000ff;">1024</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">printf</span>(<span style="color:#760f15;">&quot;js&gt; &quot;</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(<span style="color:#003369;">fgets</span>(buffer, <span style="color:#0000ff;">1024</span>, stdin) == <span style="color:#881350;">NULL</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">exit</span>(<span style="color:#0000ff;">0</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JSStringRef script = <span style="color:#003369;">JSStringCreateWithUTF8CString</span>(buffer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JSValueRef exception = <span style="color:#881350;">NULL</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(<span style="color:#003369;">JSCheckScriptSyntax</span>(ctx, script, <span style="color:#0000ff;">0</span>, <span style="color:#0000ff;">0</span>, &amp;exception) &amp;&amp; !exception)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JSValueRef value = <span style="color:#003369;">JSEvaluateScript</span>(ctx, script, <span style="color:#0000ff;">0</span>, <span style="color:#0000ff;">0</span>, <span style="color:#0000ff;">0</span>, &amp;exception);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(exception)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">JSValuePrint</span>(ctx, exception, <span style="color:#881350;">NULL</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(value &amp;&amp; !<span style="color:#003369;">JSValueIsUndefined</span>(ctx, value))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">JSValuePrint</span>(ctx, value, &amp;exception);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">else</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">printf</span>(<span style="color:#760f15;">&quot;Syntax error\n&quot;</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">JSStringRelease</span>(script);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
}</p>
<p><span style="color:#881350;">void</span> <span style="color:#003369;">JSValuePrint</span>(<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JSContextRef ctx,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JSValueRef value,<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;JSValueRef *exception)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;JSStringRef string = <span style="color:#003369;">JSValueToStringCopy</span>(ctx, value, exception);<br />
&nbsp;&nbsp;&nbsp;&nbsp;size_t length = <span style="color:#003369;">JSStringGetLength</span>(string);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">char</span> *buffer = <span style="color:#003369;">malloc</span>(length+<span style="color:#0000ff;">1</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">JSStringGetUTF8CString</span>(string, buffer, length+<span style="color:#0000ff;">1</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">JSStringRelease</span>(string);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">puts</span>(buffer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">free</span>(buffer);<br />
}</div>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2008/10/command-line-interpreter-and-repl-for-jscocoa/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Useful Mac OS X-specific command line utilities</title>
		<link>http://tlrobinson.net/blog/2008/07/useful-mac-os-x-specific-command-line-utilities/</link>
		<comments>http://tlrobinson.net/blog/2008/07/useful-mac-os-x-specific-command-line-utilities/#comments</comments>
		<pubDate>Sat, 26 Jul 2008 01:31:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Command line]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=45</guid>
		<description><![CDATA[One of the greatest strengths of Mac OS X, for developers in particular, is that it has a very elegant and consistent graphical user interface as well as an excellent command line interface. I&#8217;m not going to cover the basics &#8230; <a href="http://tlrobinson.net/blog/2008/07/useful-mac-os-x-specific-command-line-utilities/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>One of the greatest strengths of Mac OS X, for developers in particular, is that it has a very elegant and consistent graphical user interface as well as an excellent command line interface. I&#8217;m not going to cover the basics like &#8220;ls&#8221; and &#8220;cd&#8221;, but rather point out some Mac OS X specific tools that are less well known than they should be.</p>
<p>Many of these are the command line equivalents for the GUI versions available in OS X. Combining them with other command line tools can be very powerful and huge time savers. See the &#8220;man&#8221; pages for more details of each.</p>
<p><strong>open</strong> &#8211; Opens a file, application, or directory in GUI-land. Very useful.</p>
<p><strong>screencapture</strong> &#8211; Take a screenshot. Exactly the same as <command><shift> 3 or <command><shift> 4 (or even <command><shift> 4 then <space>) plus more.</p>
<p><strong>say</strong> &#8211; Text to speech. Give it a file name, string of text, or pipe the output of another program to it. Options for difference voices,<br />
saving the result to a file, etc. Fun hobby: ssh into a computer being used by someone else and start speaking to them using &#8220;say&#8221;.</p>
<p><strong>pbcopy</strong> and <strong>pbpaste</strong> &#8211; Copy and paste to/from the OS X pasteboard.</p>
<p><strong>srm</strong> &#8211; Secure &#8220;rm&#8221;. Like &#8220;rm&#8221; but overwrites deleted data. &#8220;-m&#8221; gives you DoD compliant erasing!</p>
<p><strong>osascript</strong> &#8211; Run AppleScripts (or other OSA languages) from the command line. (I use this in the &#8220;<a href="http://tlrobinson.net/blog/?p=26">term</a>&#8221; script)</p>
<p><strong>hdiutil</strong> &#8211; create and open disk images (.dmg)</p>
<p><strong>defaults</strong> &#8211; view and set various hidden settings. Check out <a href="http://www.macosxhints.com/">macosxhints.com</a> for some of these.</p>
<p>These are just a few Mac OS X specific commands I found most useful. Amit Singh has a <a href="http://www.kernelthread.com/mac/osx/tools.html">fairly comprehensive list</a> over at his excellent <a href="http://www.kernelthread.com/">kernelthread.com</a> website.</p>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2008/07/useful-mac-os-x-specific-command-line-utilities/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ANSI escape sequences in JavaScript (color on the command line!)</title>
		<link>http://tlrobinson.net/blog/2008/07/ansi-escape-sequences-in-javascript-color-on-the-command-line/</link>
		<comments>http://tlrobinson.net/blog/2008/07/ansi-escape-sequences-in-javascript-color-on-the-command-line/#comments</comments>
		<pubDate>Thu, 17 Jul 2008 01:55:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Command line]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=44</guid>
		<description><![CDATA[Recently I&#8217;ve been doing a lot of work in Rhino, Mozilla&#8217;s JavaScript interpreter written in Java. While it&#8217;s a bit slower than some of the other JavaScript interpreters out there it has the advantage of being able to call Java &#8230; <a href="http://tlrobinson.net/blog/2008/07/ansi-escape-sequences-in-javascript-color-on-the-command-line/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Recently I&#8217;ve been doing a lot of work in <a href="http://www.mozilla.org/rhino/">Rhino</a>, Mozilla&#8217;s JavaScript interpreter written in Java. While it&#8217;s a bit slower than some of the <a href="http://webkit.org/blog/189/announcing-squirrelfish/">other JavaScript interpreters</a> out there it has the advantage of being able to call Java libraries. This is immensely useful since JavaScript is pretty bare-bones in terms of built-in libraries.</p>
<p>Anyway, I had a simple logging system with the usual &#8220;error&#8221;, &#8220;warn&#8221;, &#8220;info&#8221;, etc levels, which was great except the important errors and warnings would get lost in the hundreds of info and debug messages. I didn&#8217;t know much about <a href="http://en.wikipedia.org/wiki/ANSI_escape_code">ANSI escape codes</a> except that it allows for neat things like coloring text in your terminal, so I wrote a little code to help with this:</p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; ">ANSI_ESC &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= String.<span style="color:#003369;">fromCharCode</span>(<span style="color:#0000ff;">0x1B</span>);<br />
ANSI_CSI &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= ANSI_ESC + <span style="color:#760f15;">&#8216;['</span>;<br />
ANSI_TEXT_PROP &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'m'</span>;<br />
ANSI_RESET &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'0'</span>;<br />
ANSI_BOLD &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'1'</span>;<br />
ANSI_FAINT &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'2'</span>; <span style="color:#236e25;">// unsupported?<br />
</span>ANSI_NORMAL &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'22'</span>;<br />
ANSI_ITALIC &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'3'</span>; <span style="color:#236e25;">// unsupported?<br />
</span>ANSI_UNDER &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'4'</span>;<br />
ANSI_UNDER_DBL &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'21'</span>; <span style="color:#236e25;">// unsupported?<br />
</span>ANSI_UNDER_OFF &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'24'</span>;<br />
ANSI_BLINK &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'5'</span>;<br />
ANSI_BLINK_FAST &nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'6'</span>; <span style="color:#236e25;">// unsupported?<br />
</span>ANSI_BLINK_OFF &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'25'</span>;<br />
ANSI_REVERSE &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'7'</span>;<br />
ANSI_POSITIVE &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'27'</span>;<br />
ANSI_CONCEAL &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'8'</span>;<br />
ANSI_REVEAL &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'28'</span>;<br />
ANSI_FG &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'3'</span>;<br />
ANSI_BG &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'4'</span>;<br />
ANSI_FG_INTENSE &nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'9'</span>;<br />
ANSI_BG_INTENSE &nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'10'</span>;<br />
ANSI_BLACK &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'0'</span>;<br />
ANSI_RED &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'1'</span>;<br />
ANSI_GREEN &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'2'</span>;<br />
ANSI_YELLOW &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'3'</span>;<br />
ANSI_BLUE &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'4'</span>;<br />
ANSI_MAGENTA &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'5'</span>;<br />
ANSI_CYAN &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'6'</span>;<br />
ANSI_WHITE &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;= <span style="color:#760f15;">'7'</span>;</p>
<p>ANSIControlCode = <span style="color:#881350;">function</span>(code, parameters)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(parameters == undefined)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters = <span style="color:#760f15;">&quot;&quot;</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">else</span> <span style="color:#881350;">if</span><span style="color:#003369;"> </span>(<span style="color:#881350;">typeof</span>(parameters) == <span style="color:#760f15;">'object'</span> &amp;&amp; (parameters instanceof Array))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;parameters = parameters.<span style="color:#003369;">join</span>(<span style="color:#760f15;">';'</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> ANSI_CSI + <span style="color:#003369;">String</span>(parameters) + <span style="color:#003369;">String</span>(code);<br />
}</p>
<p><span style="color:#236e25;">// simple text helpers:<br />
</span><br />
ANSITextApplyProperties = <span style="color:#881350;">function</span>(string, properties)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> <span style="color:#003369;">ANSIControlCode</span>(ANSI_TEXT_PROP, properties) + <span style="color:#003369;">String</span>(string) + <span style="color:#003369;">ANSIControlCode</span>(ANSI_TEXT_PROP);<br />
}</p>
<p><span style="color:#881350;">var</span> colorCodeMap = {<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#760f15;">&quot;black&quot;</span> &nbsp;&nbsp;: ANSI_BLACK,<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#760f15;">&quot;red&quot;</span> &nbsp;&nbsp;&nbsp;&nbsp;: ANSI_RED,<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#760f15;">&quot;green&quot;</span> &nbsp;&nbsp;: ANSI_GREEN,<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#760f15;">&quot;yellow&quot;</span> &nbsp;: ANSI_YELLOW,<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#760f15;">&quot;blue&quot;</span> &nbsp;&nbsp;&nbsp;: ANSI_BLUE,<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#760f15;">&quot;magenta&quot;</span> : ANSI_MAGENTA,<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#760f15;">&quot;cyan&quot;</span> &nbsp;&nbsp;&nbsp;: ANSI_CYAN,<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#760f15;">&quot;white&quot;</span> &nbsp;&nbsp;: ANSI_WHITE<br />
}</p>
<p>ANSITextColorize = <span style="color:#881350;">function</span>(string, color)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(colorCodeMap[color] == undefined)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> string;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> <span style="color:#003369;">ANSITextApplyProperties</span>(string, ANSI_FG + colorCodeMap[color]);<br />
}</div>
<p>Download here: <a href="http://tlrobinson.net/projects/js/ansi_sequences.js">ansi_sequences.js</a></p>
<p><strong>ANSIControlCode(code, parameters)</strong> takes in a control code as a string (a single alphabetic character, see above Wikipedia article), and zero or more parameters, either as a single string/number or array of strings/numbers (again, see above Wikipedia article). It returns a string with the control sequence.</p>
<p>There are also two helpers functions for setting text properties:</p>
<p><strong>ANSITextApplyProperties(string, properties)</strong> wraps &#8220;string&#8221; in a pair of control sequences. First the sequence to set text properties (&#8220;m&#8221; along with the given parameters), second the reset text properties sequence (&#8220;m&#8221; with no parameters). It returns the wrapped string. This lets you easily apply a number of properties to a string.</p>
<p><strong>ANSITextColorize(string, color)</strong> simply sets the foreground color of a string, and returns the wrapped string.</p>
<p>Here are examples of the helper functions:</p>
<p><img src="http://tlrobinson.net/skitches/Terminal_%E2%80%94_rlwrap_%E2%80%94_ttys003_%E2%80%94_69%C3%9716_%E2%80%94_%E2%8C%981-20080716-182921.png" alt="" /></p>
<p>Note that color control codes must be combined with either ANSI_FG or ANSI_BG.</p>
<p>Also note that this is completely useless in the browser. Only shells can understand these control codes, so use it in Rhino and other command line JavaScript interpreters (while this code is written in JavaScript, the same concepts be applied to any other programming language that can run in a shell: C, Python, Ruby, etc).</p>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2008/07/ansi-escape-sequences-in-javascript-color-on-the-command-line/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Using command line tools to detect the most frequent words in a file</title>
		<link>http://tlrobinson.net/blog/2008/03/using-command-line-tools-to-detect-the-most-frequent-words-in-a-file/</link>
		<comments>http://tlrobinson.net/blog/2008/03/using-command-line-tools-to-detect-the-most-frequent-words-in-a-file/#comments</comments>
		<pubDate>Tue, 18 Mar 2008 08:30:39 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Command line]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=35</guid>
		<description><![CDATA[Antonio Cangiano wrote a post about &#8220;[Using Python to detect the most frequent words in a file](http://antoniocangiano.com/2008/03/18/use-python-to-detect-the-most-frequent-words-in-a-file/)&#8221;. It&#8217;s a nice summary of how to do it in Python, but (nearly) the same thing can be accomplished by stringing together a &#8230; <a href="http://tlrobinson.net/blog/2008/03/using-command-line-tools-to-detect-the-most-frequent-words-in-a-file/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Antonio Cangiano wrote a post about &#8220;[Using Python to detect the most frequent words in a file](http://antoniocangiano.com/2008/03/18/use-python-to-detect-the-most-frequent-words-in-a-file/)&#8221;. It&#8217;s a nice summary of how to do it in Python, but (nearly) the same thing can be accomplished by stringing together a few standard command line tools.</p>
<p>I&#8217;m no command line ninja, but I&#8217;d like to think I have basic command of most of the standard filters. Here&#8217;s my solution:</p>
<p>    cat test.txt | tr -s &#8216;[:space:]&#8216; &#8216;\n&#8217; | tr &#8216;[:upper:]&#8216; &#8216;[:lower:]&#8216; | sort | uniq -c | sort -n | tail -10</p>
<p>I&#8217;ll explain it blow-by-blow:</p>
<p>    cat test.txt</p>
<p>If you don&#8217;t know what this does you&#8217;ve got a lot to learn. &#8220;cat&#8221; simply reads files and prints them to standard output (con<strong>cat</strong>enates), for use by subsequent filters.</p>
<p>    tr -s &#8216;[:space:]&#8216; &#8216;\n&#8217;</p>
<p>&#8220;tr&#8221; is a handy tool that simply <strong>tr</strong>anslates matching characters from the first set to the corresponding character of the second set. The first instance turns all whitespace characters (spaces, tabs, newlines) into newlines (&#8220;\n&#8221;) so that each word is on a separate line (the -s option &#8220;squeezes&#8221; multiple runs of newlines into a single newline).</p>
<p>    tr &#8216;[:upper:]&#8216; &#8216;[:lower:]&#8216;</p>
<p>The second instance translates all uppercase characters into lowercase (note: the two &#8220;tr&#8221;s are separate for clarity, but they could be combined into a single one).</p>
<p>    sort | uniq -c</p>
<p>&#8220;sort&#8221; and &#8220;uniq&#8221; do exactly as their names imply, but &#8220;uniq&#8221; only removes adjacent duplicates, so you often want to sort the input first. The &#8220;-c&#8221; option for &#8220;uniq&#8221; prepends each line with the number of occurrences.</p>
<p>    sort -n</p>
<p>We sort the result of &#8220;uniq&#8221;, this time by numerical order (&#8220;-n&#8221;) to get the list of words in order of the number of occurrences.</p>
<p>    tail -10</p>
<p>Finally, we get the 10 most frequently occurring words by using &#8220;tail&#8221; to take only the last 10 lines (since the &#8220;sort -n&#8221; puts the list in ascending order)</p>
<p>It&#8217;s not perfect, especially since punctuation is included in the words, but the &#8220;tr&#8221; commands can be tweaked as needed.</p>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2008/03/using-command-line-tools-to-detect-the-most-frequent-words-in-a-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Presenting GCCalc: a horrible abuse of GCC</title>
		<link>http://tlrobinson.net/blog/2007/12/presenting-gccalc-a-horribly-awesome-abuse-of-gcc/</link>
		<comments>http://tlrobinson.net/blog/2007/12/presenting-gccalc-a-horribly-awesome-abuse-of-gcc/#comments</comments>
		<pubDate>Fri, 14 Dec 2007 09:02:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[C]]></category>
		<category><![CDATA[Command line]]></category>
		<category><![CDATA[GCC]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=31</guid>
		<description><![CDATA[Following an [interesting discussion on Reddit](http://programming.reddit.com/info/62v70/comments) about [first class functions](http://en.wikipedia.org/wiki/First-class_function) in C, I was inspired to see what I could do with this new-found knowledge. The result is what I affectionately call &#8220;GCCalc&#8221;, for reasons that will become clear below. &#8230; <a href="http://tlrobinson.net/blog/2007/12/presenting-gccalc-a-horribly-awesome-abuse-of-gcc/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Following an [interesting discussion on Reddit](http://programming.reddit.com/info/62v70/comments) about [first class functions](http://en.wikipedia.org/wiki/First-class_function) in C, I was inspired to see what I could do with this new-found knowledge. The result is what I affectionately call &#8220;GCCalc&#8221;, for reasons that will become clear below.</p>
<p>GCCalc is a simple command line calculator, much like the common [bc](http://en.wikipedia.org/wiki/Bc_programming_language) calculator on many Unix systems. It&#8217;s implementation, however, is *very* different than most calculators. While bc is said to have &#8220;C-like syntax&#8221;, GCCalc&#8217;s syntax *is* C. Whatever you enter on the command line automatically gets compiled, loaded, and executed, and the result is returned (as a double) and printed to the screen.</p>
<p>You can either enter expressions like:</p>
<p>    round(46.95886*sqrt(1+2/9.99*sin((21%5)*pow(2,8))))</p>
<p>or you can enter whole C statements (as long as they&#8217;re on one line, for now) like:</p>
<p>     int i; for (i=0;i<10;i++) { printf("hello world!\n"); } printf("goodbye\n");</p>
<p>Unfortunately variables are scoped to the function that wraps them, so they don't persist across multiple entries. However, you can access the last result using the "last" variable (a double).</p>
<p>[Here's the source file](http://tlrobinson.net/projects/gccalc/gccalc.c), and here's a syntax highlighted version:</p>
<p>It's been tested on Mac OS X (Leopard) and Linux (Ubuntu Gutsy), with GCC 4. Compile with "gcc -o gccalc gccalc.c" on OS X, or "gcc -o gccalc gccalc.c -ldl" on Linux.</p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; ">
<span style="color:#683821;">#include &lt;stdio.h&gt;<br />
#include &lt;stdlib.h&gt;<br />
#include &lt;string.h&gt;<br />
#include &lt;dlfcn.h&gt;<br />
#include &lt;unistd.h&gt;<br />
</span><br />
<span style="color:#683821;">#ifdef __ELF__<br />
#define GCC_FLAGS &quot;-fPIC -shared&quot;<br />
#define EXTENSION &quot;so&quot;<br />
#else<br />
#define GCC_FLAGS &quot;-dynamiclib&quot;<br />
#define EXTENSION &quot;dylib&quot;<br />
#endif<br />
</span><br />
<span style="color:#683821;">#define HEADERS &quot;#include &lt;stdio.h&gt;\n#include&lt;math.h&gt;&quot;<br />
</span><br />
<span style="color:#881350;">typedef</span> <span style="color:#881350;">double</span>(func_return_double)(<span style="color:#881350;">double</span>);</p>
<p><span style="color:#881350;">unsigned</span> count = <span style="color:#0000ff;">0</span>;<br />
<span style="color:#881350;">char</span> *cwd;<br />
<span style="color:#881350;">char</span> tmp_path[<span style="color:#0000ff;">1024</span>] = {<span style="color:#0000ff;">&#8216;\0&#8242;</span>};</p>
<p><span style="color:#881350;">void</span> *lib = <span style="color:#881350;">NULL</span>;</p>
<p><span style="color:#881350;">int</span> <span style="color:#003369;">main</span>(<span style="color:#881350;">int</span> argc, <span style="color:#881350;">char</span> **argv)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">double</span> result = <span style="color:#0000ff;">0.0</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">char</span> input_buffer[<span style="color:#0000ff;">1024</span>], code_buffer[<span style="color:#0000ff;">2048</span>], function_name[<span style="color:#0000ff;">32</span>], command_buffer[<span style="color:#0000ff;">1024</span>];<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// get out current directory, which we&#8217;ll use for tmp files (dlopen seems to need absolute paths)<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;cwd = <span style="color:#003369;">getcwd</span>(<span style="color:#881350;">NULL</span>, <span style="color:#0000ff;">0</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">while</span><span style="color:#003369;"> </span>(<span style="color:#0000ff;">1</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// for unique function and file names (needed for dlopen/dlsym to work correctly)<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count++;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// read in the next line<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">printf</span>(<span style="color:#760f15;">&quot;&gt;&gt; &quot;</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">fgets</span>(input_buffer, <span style="color:#881350;">sizeof</span>(input_buffer), stdin);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// format the function name<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">sprintf</span>(function_name, <span style="color:#760f15;">&quot;f%d&quot;</span>, count);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// format the code string: if it doesn&#8217;t contain a semicolon, assume it is just an expression<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(<span style="color:#003369;">strchr</span>(input_buffer, <span style="color:#0000ff;">&#8216;;&#8217;</span>))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">sprintf</span>(code_buffer, <span style="color:#760f15;">&quot;%s\ndouble %s(double last) { %s\nreturn 0; }&quot;</span>, HEADERS, function_name, input_buffer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">else</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">sprintf</span>(code_buffer, <span style="color:#760f15;">&quot;%s\ndouble %s(double last) { return (%s); }&quot;</span>, HEADERS, function_name, input_buffer);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// format the filename string, delete the file if it exists<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">sprintf</span>(tmp_path, <span style="color:#760f15;">&quot;%s/libtmp%d.%s&quot;</span>, cwd, count, EXTENSION);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">unlink</span>(tmp_path);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// format the gcc command string<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">sprintf</span>(command_buffer, <span style="color:#760f15;">&quot;gcc -Wall %s -x c &#8211; -o %s&quot;</span>, GCC_FLAGS, tmp_path);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// execute gcc command, write out the code<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;FILE *fp = <span style="color:#003369;">popen</span>(command_buffer, <span style="color:#760f15;">&quot;w&quot;</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">fwrite</span>(code_buffer, <span style="color:#0000ff;">1</span>, <span style="color:#003369;">strlen</span>(code_buffer), fp);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">fprintf</span>(fp, <span style="color:#760f15;">&quot;\n&quot;</span>);<br />
&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// pclose waits for gcc to terminate (fclose/close do NOT thus compilation will sometimes not finish prior to the dlopen)<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">pclose</span>(fp);</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">void</span> *ptr = <span style="color:#881350;">NULL</span>;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// open the just-compiled dynamic library<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>((lib = <span style="color:#003369;">dlopen</span>(tmp_path, RTLD_NOW|RTLD_LOCAL)) == <span style="color:#881350;">NULL</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">puts</span>(<span style="color:#003369;">dlerror</span>());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// get the function pointer<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">else</span> <span style="color:#881350;">if</span><span style="color:#003369;"> </span>((ptr = <span style="color:#003369;">dlsym</span>(lib, function_name)) == <span style="color:#881350;">NULL</span>) {<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">puts</span>(<span style="color:#003369;">dlerror</span>());<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// execute it<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">if</span><span style="color:#003369;"> </span>(ptr != <span style="color:#881350;">NULL</span>)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;func_return_double *func = (func_return_double*)ptr;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;result = (*func)(result);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// print the result<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">printf</span>(<span style="color:#760f15;">&quot;=&gt; %.*lf\n&quot;</span>, (result/((<span style="color:#881350;">int</span>)result)&gt;<span style="color:#0000ff;">1.0</span>)?<span style="color:#0000ff;">5</span>:<span style="color:#0000ff;">0</span>, result);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#236e25;">// clean up: close the library, delete the temp file<br />
</span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">dlclose</span>(lib);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#003369;">unlink</span>(tmp_path);<br />
&nbsp;&nbsp;&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#881350;">return</span> <span style="color:#0000ff;">0</span>;<br />
}
</div>
<p>Thanks to jbert on Reddit for the initial code and inspiration.</p>
<p>If only I had known about this back when The Daily WTF has having their [OMG WTF](http://omg.thedailywtf.com/) crazy calculator programming contest&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2007/12/presenting-gccalc-a-horribly-awesome-abuse-of-gcc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Open new Terminal window in current (or other specified) directory</title>
		<link>http://tlrobinson.net/blog/2007/09/open-new-terminal-window-in-current-or-other-specified-directory/</link>
		<comments>http://tlrobinson.net/blog/2007/09/open-new-terminal-window-in-current-or-other-specified-directory/#comments</comments>
		<pubDate>Fri, 07 Sep 2007 21:38:18 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Command line]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=26</guid>
		<description><![CDATA[A lot of times I find myself wanting to open another (Mac OS X) Terminal window in the same directory as my current one. This little shell script, which executes a little AppleScript, makes that trivial: #!/bin/sh if [ $# &#8230; <a href="http://tlrobinson.net/blog/2007/09/open-new-terminal-window-in-current-or-other-specified-directory/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>A lot of times I find myself wanting to open another (Mac OS X) Terminal window in the same directory as my current one. This little shell script, which executes a little AppleScript, makes that trivial:</p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; "><span style="color:#236e25;">#!/bin/sh<br />
</span><br />
<span style="color:#881350;">if</span> [ <span style="color:#c4620a;">$#</span> -ne <span style="color:#0000ff;">1</span> ]; <span style="color:#881350;">then</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;PATHDIR=<span style="color:#660088;">`pwd`</span><br />
<span style="color:#881350;">else</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;PATHDIR=<span style="color:#c4620a;">$</span><span style="color:#0000ff;">1</span><br />
<span style="color:#881350;">fi</span></p>
<p>osascript -e <span style="color:#760f15;">&quot;tell application \&quot;Terminal\&quot;&quot;</span> -e <span style="color:#760f15;">&quot;do script \&quot;cd </span><span style="color:#c4620a;">$PATHDIR</span><span style="color:#760f15;">\&quot;&quot;</span> -e <span style="color:#760f15;">&quot;end tell&quot;</span>
</div>
<p>Save this script somewhere in your $PATH with executable permissions. Now instead of hitting Command-N then typing &#8220;cd really/long/path/to/your/current/directory&#8221;, you can simply type the name of the script (I used &#8220;term&#8221;):</p>
<p>    term</p>
<p>Chain them together to open multiple windows. The following would open three new windows with the same current directory:</p>
<p>    term; term; term</p>
<p>It can also take an optional directory path argument to override the current directory:</p>
<p>    term /System/Library/</p>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2007/09/open-new-terminal-window-in-current-or-other-specified-directory/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>multiwhich</title>
		<link>http://tlrobinson.net/blog/2007/08/multiwhich/</link>
		<comments>http://tlrobinson.net/blog/2007/08/multiwhich/#comments</comments>
		<pubDate>Thu, 16 Aug 2007 05:51:54 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Command line]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>

		<guid isPermaLink="false">http://tlrobinson.net/blog/?p=19</guid>
		<description><![CDATA[The &#8220;which&#8221; Unix command lists the location of the first matching executable in your PATH. The GNU version of &#8220;which&#8221; has several extra features including the ability to display all matching executables in your PATH, not just the first. This &#8230; <a href="http://tlrobinson.net/blog/2007/08/multiwhich/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>The &#8220;which&#8221; Unix command lists the location of the first matching executable in your PATH. The GNU version of &#8220;which&#8221; has several extra features including the ability to display <strong>all</strong> matching executables in your PATH, not just the first. This is useful for finding duplicates, etc. Unfortunately, whatever version of &#8220;which&#8221; is included in Mac OS X (and MacPorts) doesn&#8217;t have these extra features.</p>
<p>A quick Google search didn&#8217;t turn up anything, and I was in a shell scripting mood when I needed it, so rather than downloading and compiling GNU which I whipped up my own, &#8220;multiwhich&#8221;:</p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; "><span style="color:#236e25;">#!/bin/sh<br />
</span><br />
<span style="color:#881350;">for</span> PATHDIR <span style="color:#881350;">in</span> <span style="color:#660088;">`echo $PATH | tr &quot;:&quot; &quot; &quot;`</span><br />
<span style="color:#881350;">do</span><br />
&nbsp;&nbsp;&nbsp;&nbsp;<span style="color:#880088;">sh</span> -c <span style="color:#760f15;">&quot;ls -1 </span><span style="color:#c4620a;">$PATHDIR</span><span style="color:#760f15;">/</span><span style="color:#c4620a;">$1</span><span style="color:#760f15;">&quot;</span> <span style="color:#0000ff;">2</span>&gt; /dev/null<br />
<span style="color:#881350;">done</span></div>
<p>Simply put this somewhere in your PATH with execute permissions, and type &#8220;which <em>command</em>&#8220;.</p>
<p>One other accidental &#8220;feature&#8221; of this script is the ability to list <strong>every</strong> executable in your PATH. This is great for finding duplicates:</p>
<div style="text-align:left;color:#000000; background-color:#ffffff; border:solid black 1px; padding:0.5em 1em 0.5em 1em; overflow:auto;font-size:small; font-family:monospace; ">multiwhich | <span style="color:#880088;">sort</span> | <span style="color:#880088;">uniq</span> -c | <span style="color:#880088;">sort</span> -n</div>
<p>It&#8217;s probably not the most elegant way to do it, but it serves it&#8217;s purpose. Perhaps someone will find it useful&#8230;</p>
<p><em>Update: I modified the multiwhich script slightly to support wildcards like &#8220;*&#8221; and &#8220;?&#8221;. You can now do things like &#8220;multiwhich x*&#8221; to get all binaries beginning with &#8220;x&#8221;, etc.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://tlrobinson.net/blog/2007/08/multiwhich/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

