<?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>hasseg.org &#187; Scripts</title>
	<atom:link href="http://hasseg.org/blog/post/category/scripts/feed/" rel="self" type="application/rss+xml" />
	<link>http://hasseg.org/blog</link>
	<description></description>
	<lastBuildDate>Sun, 29 Apr 2012 09:35:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>jEdit Macro for Opening the File Browser at Current Buffer&#8217;s &#8220;Project Root&#8221; Directory</title>
		<link>http://hasseg.org/blog/post/619/jedit-macro-for-opening-the-file-browser-at-current-buffers-project-root-directory/</link>
		<comments>http://hasseg.org/blog/post/619/jedit-macro-for-opening-the-file-browser-at-current-buffers-project-root-directory/#comments</comments>
		<pubDate>Wed, 13 Oct 2010 15:26:01 +0000</pubDate>
		<dc:creator>Ali Rantakari</dc:creator>
				<category><![CDATA[jEdit]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://hasseg.org/blog/?p=619</guid>
		<description><![CDATA[When I&#8217;m working with code in jEdit, my editor of choice, I like to keep the file browser open and docked to the left side of my editor window. When I&#8217;m switching between files &#8212; often belonging to different projects &#8212; I find myself reaching for the mouse in order to manually navigate the file [...]]]></description>
			<content:encoded><![CDATA[<p>
<img align="right" src="http://hasseg.org/blog/wp-content/uploaded/2007/09/jediticon.jpeg" alt="" width="53" height="53" /> When I&#8217;m working with code in jEdit, my editor of choice, I like to keep the file browser open and docked to the left side of my editor window. When I&#8217;m switching between files &#8212; often belonging to different projects &#8212; I find myself <strong>reaching for the mouse</strong> in order to manually navigate the file browser to the root folder of the project the currently open file belongs to. I started doing this so often that I decided to <strong>whip up a small macro to do it for me</strong>.
</p>
<div class="note">
<strong>Update (April 4, 2011):</strong> Set file browser to directory of current buffer if version control root cannot be found.
</div>
<p><span id="more-619"></span></p>
<p>
Since I don&#8217;t use the <a href="http://plugins.jedit.org/plugins/?ProjectViewer">ProjectViewer</a> plugin this macro has to have its own logic for determining where the &#8220;project root&#8221; is. The way it works is that it tries to <strong>find the root folder</strong> of the current project by way of <strong>searching for version control system folders</strong> (i.e. <span style="font-family:monospace">.git</span>, <span style="font-family:monospace">.hg</span>, <span style="font-family:monospace">.bzr</span>, <span style="font-family:monospace">_darcs</span>, <span style="font-family:monospace">.svn</span> or <span style="font-family:monospace">CVS</span>). The assumption is that as the script traverses the file system folder structure from the buffer&#8217;s location towards the root the <em>first</em> folder that has a Git, Mercurial, Bazaar or Darcs folder (or the <em>last</em> to have a Subversion or CVS folder) is the root. When the script finds the project root it switches the file browser to display it while keeping the UI focus in the editor field. If no project root can be found in this manner, the script sets the file browser to the directory that contains the currently open file.
</p>
<p>
<strong>Download</strong> the macro script itself here: <a href="/stuff/jEditMacros/Open_Root_of_Current_Project_in_File_Browser.bsh">Open_Root_of_Current_Project_in_File_Browser.bsh</a>
</p>
<p>
You install it by dropping it into your jEdit user settings directory&#8217;s <span style="font-family:monospace">/macros</span> folder (select <em>Utilities &rarr; Settings Directory</em> from the jEdit menu to find this location) and then running <em>Macros &rarr; Rescan Macros</em>. You can set a keyboard shortcut for this via the <em>Shortcuts</em> section of jEdit&#8217;s preferences and/or add a toolbar button via the <em>Tool Bar</em> section.
</p>
<p>Here is the macro source:</p>
<div class="codecolorer-container java mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="java codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #008000; font-style: italic; font-weight: bold;">/**<br />
&nbsp;* Tries to find the root of the 'current project', assuming<br />
&nbsp;* all project files live under the same directory structure<br />
&nbsp;* and that they are all under the same version control<br />
&nbsp;* repository.<br />
&nbsp;* <br />
&nbsp;* For Git, Mercurial and Bazaar (and it seems Darcs?) this is<br />
&nbsp;* easy since they only have their 'dot-directory' at the root<br />
&nbsp;* of the structure but Subversion (and I assume CVS) put them<br />
&nbsp;* everywhere so we have to find the _last_ directory to have<br />
&nbsp;* one.<br />
&nbsp;* <br />
&nbsp;*/</span><br />
<span style="color: #003399;">String</span> findProjectRoot<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; dir <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> <span style="color: #003399;">File</span><span style="color: #009900;">&#40;</span>buffer.<span style="color: #006633;">getDirectory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; previousDir <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">boolean</span> previousDirHasSvnDir <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">boolean</span> previousDirHasCvsDir <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">while</span> <span style="color: #009900;">&#40;</span>dir <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">boolean</span> hasSvnDir <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">boolean</span> hasCvsDir <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">false</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; list <span style="color: #339933;">=</span> dir.<span style="color: #006633;">list</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #009900;">&#40;</span>childName <span style="color: #339933;">:</span> list<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>hasSvnDir <span style="color: #339933;">&amp;&amp;</span> childName.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;.svn&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hasSvnDir <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>hasCvsDir <span style="color: #339933;">&amp;&amp;</span> childName.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;CVS&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; hasCvsDir <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">true</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">else</span> <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>childName.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;.git&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">||</span> childName.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;.hg&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">||</span> childName.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;.bzr&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">||</span> childName.<span style="color: #006633;">equals</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;_darcs&quot;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> dir.<span style="color: #006633;">getAbsolutePath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>previousDir <span style="color: #339933;">!=</span> <span style="color: #000066; font-weight: bold;">null</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span>previousDirHasSvnDir <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>hasSvnDir<span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #339933;">||</span> <span style="color: #009900;">&#40;</span>previousDirHasCvsDir <span style="color: #339933;">&amp;&amp;</span> <span style="color: #339933;">!</span>hasCvsDir<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> previousDir.<span style="color: #006633;">getAbsolutePath</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; previousDirHasSvnDir <span style="color: #339933;">=</span> hasSvnDir<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; previousDirHasCvsDir <span style="color: #339933;">=</span> hasCvsDir<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; previousDir <span style="color: #339933;">=</span> dir<span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; dir <span style="color: #339933;">=</span> dir.<span style="color: #006633;">getParentFile</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<br />
root <span style="color: #339933;">=</span> findProjectRoot<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000000; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>root <span style="color: #339933;">==</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #009900;">&#41;</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; VFSBrowser.<span style="color: #006633;">browseDirectory</span><span style="color: #009900;">&#40;</span>view, buffer.<span style="color: #006633;">getDirectory</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; view.<span style="color: #006633;">getEditPane</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">focusOnTextArea</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; view.<span style="color: #006633;">getStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">setMessageAndClear</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Browser directory set to current buffer's location (cannot find project root.).&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span><br />
<span style="color: #000000; font-weight: bold;">else</span><br />
<span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; VFSBrowser.<span style="color: #006633;">browseDirectory</span><span style="color: #009900;">&#40;</span>view, root<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; view.<span style="color: #006633;">getEditPane</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">focusOnTextArea</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; view.<span style="color: #006633;">getStatus</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">setMessageAndClear</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Project root guessed; browser directory set to it.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #009900;">&#125;</span></div></div>
]]></content:encoded>
			<wfw:commentRss>http://hasseg.org/blog/post/619/jedit-macro-for-opening-the-file-browser-at-current-buffers-project-root-directory/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting Events/Tasks From the OS X Calendar Store in a Custom Format like XML, CSV or LaTeX</title>
		<link>http://hasseg.org/blog/post/602/getting-eventstasks-from-the-os-x-calendar-store-in-a-custom-format-like-xml-csv-or-latex/</link>
		<comments>http://hasseg.org/blog/post/602/getting-eventstasks-from-the-os-x-calendar-store-in-a-custom-format-like-xml-csv-or-latex/#comments</comments>
		<pubDate>Wed, 13 Oct 2010 14:49:41 +0000</pubDate>
		<dc:creator>Ali Rantakari</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://hasseg.org/blog/?p=602</guid>
		<description><![CDATA[Over the past couple of years I&#8217;ve gotten a few emails from users of icalBuddy who would like to somehow automate the task of generating CSV, XML/HTML or LaTeX output from the items in their calendar. Unfortunately icalBuddy isn&#8217;t set up to provide any kind of arbitrary output format (and I didn&#8217;t want to re-architect [...]]]></description>
			<content:encoded><![CDATA[<p>
<img src="http://hasseg.org/blog/wp-content/uploaded/2010/08/PyCalXMLCSVLaTeX.png" alt="" width="106" height="83" align="right" /> Over the past couple of years I&#8217;ve gotten a few emails from users of <a href="/icalBuddy">icalBuddy</a> who would like to somehow automate the task of generating <em>CSV</em>, <em>XML/HTML</em> or <em>LaTeX</em> output from the items in their calendar. Unfortunately icalBuddy isn&#8217;t set up to provide any kind of arbitrary output format (and I didn&#8217;t want to re-architect it to do that) but a while ago I finally had the time and motivation to figure out a small solution for this: a Python helper class for writing scripts that produce whatever type of output your heart desires.
</p>
<p><span id="more-602"></span></p>
<p>
This class is called <a href="/calStoreHelper">CalStoreHelper</a> and it provides you with <a href="/calStoreHelper/CalStoreHelper.CalStoreHelper.html">two methods</a>: one for getting events and the other for getting tasks. An <a href="/hgweb/calStoreHelper/file/tip/example.py">example script</a> shows you concretely how to generate different kinds of output. Below is a small excerpt that shows how to generate CSV output:
</p>
<div class="codecolorer-container python mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span><br />
<span style="color: #ff7700;font-weight:bold;">from</span> CalStoreHelper <span style="color: #ff7700;font-weight:bold;">import</span> *<br />
<span style="color: #ff7700;font-weight:bold;">from</span> CalendarStore <span style="color: #ff7700;font-weight:bold;">import</span> *<br />
<br />
<br />
c <span style="color: #66cc66;">=</span> CalStoreHelper<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;"># List of calendars to query (use None for all calendars)</span><br />
calendar_names <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'Home'</span><span style="color: #66cc66;">,</span><span style="color: #483d8b;">'Work'</span><span style="color: black;">&#93;</span><br />
<br />
<span style="color: #808080; font-style: italic;"># Start and end dates to get events between</span><br />
start_date <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">datetime</span>.<span style="color: #dc143c;">datetime</span>.<span style="color: black;">now</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
delta <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">datetime</span>.<span style="color: black;">timedelta</span><span style="color: black;">&#40;</span>days<span style="color: #66cc66;">=</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><br />
end_date <span style="color: #66cc66;">=</span> start_date + delta<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> example_CSV<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Example: get events + CSV formatting</span><br />
&nbsp; &nbsp; events <span style="color: #66cc66;">=</span> c.<span style="color: black;">getEvents</span><span style="color: black;">&#40;</span>calendar_names<span style="color: #66cc66;">,</span> start_date<span style="color: #66cc66;">,</span> end_date<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> UnicodeCSV <span style="color: #ff7700;font-weight:bold;">import</span> UnicodeWriter<br />
&nbsp; &nbsp; csv_writer <span style="color: #66cc66;">=</span> UnicodeWriter<span style="color: black;">&#40;</span><span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/dev/stdout'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">for</span> event <span style="color: #ff7700;font-weight:bold;">in</span> events:<br />
&nbsp; &nbsp; &nbsp; &nbsp; csv_writer.<span style="color: black;">writerow</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; event.<span style="color: #dc143c;">calendar</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">title</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; event.<span style="color: black;">title</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; event.<span style="color: black;">location</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; event.<span style="color: black;">startDate</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">descriptionWithCalendarFormat_timeZone_locale_</span><span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">None</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; event.<span style="color: black;">endDate</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">descriptionWithCalendarFormat_timeZone_locale_</span><span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">None</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; event.<span style="color: black;">notes</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></div></div>
<p>
You can get the class by cloning the <a href="/calStoreHelper/#scmRepoInfo">version control repository</a> with <a href="http://mercurial.selenic.com/">Mercurial</a> or by downloading an archive from the <a href="/hgweb/calStoreHelper/">repository browser page</a> <em>(the bz2, zip and gz links at the top)</em>. Happy hacking.</p>
]]></content:encoded>
			<wfw:commentRss>http://hasseg.org/blog/post/602/getting-eventstasks-from-the-os-x-calendar-store-in-a-custom-format-like-xml-csv-or-latex/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Use Unicode Emoji as Image-Free Icons in iOS Web Apps</title>
		<link>http://hasseg.org/blog/post/546/use-unicode-emoji-as-image-free-icons-in-ios-web-apps/</link>
		<comments>http://hasseg.org/blog/post/546/use-unicode-emoji-as-image-free-icons-in-ios-web-apps/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 22:59:37 +0000</pubDate>
		<dc:creator>Ali Rantakari</dc:creator>
				<category><![CDATA[iOS]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://hasseg.org/blog/?p=546</guid>
		<description><![CDATA[In version 2.2 of iOS &#8212; Apple&#8217;s &#8220;mobile&#8221; operating system used in the iPhone, iPod Touch and iPad &#8212; support for Emoji was added. These small 12&#215;12 pixel icons are meant to be used in text messaging in Japan but because they&#8217;re implemented simply as unicode symbols in the device they can be used as [...]]]></description>
			<content:encoded><![CDATA[<p>
<img src="http://hasseg.org/blog/wp-content/uploaded/2010/07/emoji-small.png" alt="" title="" width="57" height="57" align="right" /> In version 2.2 of <a href="http://en.wikipedia.org/wiki/IOS_(Apple)">iOS</a> &mdash; Apple&#8217;s &#8220;mobile&#8221; operating system used in the <em>iPhone</em>, <em>iPod Touch</em> and <em>iPad</em> &mdash; support for <a href="http://en.wikipedia.org/wiki/Emoji">Emoji</a> was added. These small 12&#215;12 pixel icons are meant to be used in text messaging in Japan but because they&#8217;re implemented simply as unicode symbols in the device <strong>they can be used as icons</strong> when we know they&#8217;re available.
</p>
<p><span id="more-546"></span></p>
<h2>Emoji and Unicode</h2>
<p>
Emoji is basically a Japanese term for emoticons used on mobile devices. <a href="http://en.wikipedia.org/wiki/Emoji">The Wikipedia article</a> has more information on the concept, but this part is the most interesting:
</p>
<blockquote><p>
When transmitted, emoji symbols are specified as a two-byte sequence, in the private-use range E63E through E757 in the Unicode character space, or F89F through F9FC for Shift-JIS.
</p></blockquote>
<p>
Now, that&#8217;s <em>not true</em> for Apple&#8217;s Emoji implementation &mdash; it&#8217;s apparently completely incompatible with the handsets from the Japanese carriers (see <a href="http://openradar.appspot.com/6402446">OpenRadar #6402446</a> for more info) &mdash; but the part about them being implemented as unicode symbols <em>is</em> still true in iOS, the code points used are just different.
</p>
<p>
I&#8217;ve made <a href="/stuff/ios-emoji/">this demo page</a> that <strong>lists unicode symbols and the hexadecimal code points for all the different Emoji that are available on my iPhone</strong> (iOS version 4). The demo page has a cache manifest so it should be available offline as well. If you&#8217;re currently on a desktop computer you won&#8217;t be able to see them so here&#8217;s a picture of what it looks like on the iPhone:
</p>
<div style="text-align:center;">
<img src="http://hasseg.org/blog/wp-content/uploaded/2010/07/emoji-page.png" alt="" title="" width="229" height="335" />
</div>
<p>
In order to be able to use these icons you need to have easy access to the hexadecimal unicode code points so this page should come in handy. If you instead prefer a native app for this, there are <a href="http://www.google.com/search?q=site%3Aitunes.apple.com+inurl%3A%22%2Fapp%2F%22+unicode">many you can choose from</a>.
</p>
<h2>Using Emoji Symbols in HTML and CSS</h2>
<p>
User agent detection is usually cited as a bad thing, and with good reason &mdash; it&#8217;s often used when <a href="http://diveintohtml5.org/detect.html">feature detection</a> would be more appropriate, causing unexpected breakage in many edge conditions. When planning on using the iOS emoji on a web page, though, <strong>you really need to sniff the user agent</strong> in order to know whether the client is an iOS device and thus has a font that implements these unicode symbols in the expected way.
</p>
<p>
Here&#8217;s an example (in PHP) of how you&#8217;d detect iOS devices:
</p>
<div class="codecolorer-container php mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #000088;">$is_iPhone</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_USER_AGENT'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'iPhone'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$is_iPod</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_USER_AGENT'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'iPod'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$is_iPad</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #990000;">strpos</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$_SERVER</span><span style="color: #009900;">&#91;</span><span style="color: #0000ff;">'HTTP_USER_AGENT'</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">'iPad'</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">!==</span> <span style="color: #009900; font-weight: bold;">false</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
<span style="color: #000088;">$is_iOS</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$is_iPad</span> <span style="color: #339933;">||</span> <span style="color: #000088;">$is_iPod</span> <span style="color: #339933;">||</span> <span style="color: #000088;">$is_iPhone</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<p>
When you&#8217;ve detected the client to be an iOS device, you can <strong>offer them an additional stylesheet:</strong>
</p>
<div class="codecolorer-container php mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="php codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000088;">$is_iOS</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #b1b100;">echo</span> <span style="color: #0000ff;">'&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;iOS.css&quot; /&gt;'</span><span style="color: #339933;">;</span></div></div>
<p>
In this stylesheet you&#8217;ll then insert the Emoji symbols into whatever locations you&#8217;d like to use them in, and to do this you can use <a href="http://www.w3.org/TR/CSS2/generate.html">CSS2&#8242;s content generation mechanisms</a> (in the examples below, we use code point E00E, which is the &#8220;thumbs up&#8221; Emoji):
</p>
<div class="codecolorer-container css mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="css codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #cc00cc;">#someID</span><span style="color: #3333ff;">:before </span><span style="color: #00AA00;">&#123;</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">content</span><span style="color: #00AA00;">:</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\E00E</span>&quot;</span><span style="color: #00AA00;">;</span> <span style="color: #808080; font-style: italic;">/* thumbs up */</span><br />
&nbsp; &nbsp; <span style="color: #000000; font-weight: bold;">margin-right</span><span style="color: #00AA00;">:</span> <span style="color: #933;">5px</span><span style="color: #00AA00;">;</span><br />
<span style="color: #00AA00;">&#125;</span></div></div>
<p>
Containing all the iOS-specific embellishments in one separate CSS file is, I think, the way to go, but if you want you can also insert these symbols directly into your HTML as special entities:
</p>
<div class="codecolorer-container html4strict mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #009900;">&lt;<span style="color: #000000; font-weight: bold;">div</span>&gt;</span><span style="color: #ddbb00;">&amp;#xE00E;</span> Thumbs up!<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><span style="color: #000000; font-weight: bold;">div</span>&gt;</span></div></div>
<h2>Big Caveats to Consider</h2>
<p>
This is a great way to add little graphical cues to your web app <strong>without having to deal with images</strong> (i.e. making or obtaining them, serving them, having the app load them, possibly caching them) but of course the downside is that they are <strong>only available on Apple&#8217;s iOS devices</strong>, which makes this trick quite useless unless you&#8217;re concentrating completely on the iPhone/iPad/iPod Touch axis.
</p>
<p>
The key takeaway from this should be that there&#8217;s this <strong>neat trick</strong> you can use but <strong>if you <em>need</em> your icons to be visible in all clients</strong> you should forget about these and <strong>just use images for everyone</strong> (it&#8217;ll be much easier).
</p>
<div class="note" style="margin-bottom:50px;"><strong>Note:</strong> I&#8217;ve noticed that for some reason these emoji characters will <strong>fail to render on the iPad if the <span style="font-family:monospace;">text-rendering</span> CSS property is set to <span style="font-family:monospace;">optimizeLegibility</span></strong> <em>(this is on the iPad-specific build of iOS 3.2, MobileSafari Version/4.0.4 Mobile/7B367 Safari/531.21.10 and does not occur on my iPhone (which is running iOS 4.0.1))</em>.</div>
]]></content:encoded>
			<wfw:commentRss>http://hasseg.org/blog/post/546/use-unicode-emoji-as-image-free-icons-in-ios-web-apps/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Prevent iTunes websites from opening the iTunes app using GlimmerBlocker</title>
		<link>http://hasseg.org/blog/post/441/prevent-itunes-websites-from-opening-the-itunes-app-using-glimmerblocker/</link>
		<comments>http://hasseg.org/blog/post/441/prevent-itunes-websites-from-opening-the-itunes-app-using-glimmerblocker/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 21:41:57 +0000</pubDate>
		<dc:creator>Ali Rantakari</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Miscallaneous]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://hasseg.org/blog/?p=441</guid>
		<description><![CDATA[A few minutes ago I clicked on an iTunes store link on a website and had to again completely lose it because of the iTunes app popping up without me asking it to. This is a common annoyance that people have found a bunch of different ways to combat, ranging from messing with the system&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>
<img align="right" src="http://hasseg.org/blog/wp-content/uploaded/2010/04/itunes-kickass.png" alt="" width="115" height="96" /> A few minutes ago I clicked on an iTunes store link on a website and had to again completely <em>lose it</em> because of the iTunes app popping up without me asking it to. This is a common annoyance that people have found a bunch of different ways to combat, ranging from messing with the system&#8217;s (or the browser&#8217;s) mapping of URL protocol handlers to rewriting parts of web pages via a browser plugin (e.g. GreaseMonkey) or a localhost web proxy (e.g. GlimmerBlocker).
</p>
<p><span id="more-441"></span></p>
<div class="note">
<strong>Note (Aug &#8217;10):</strong> Now that Safari 5 has support for extensions, installing the <a href="http://einserver.de/nomoreitunes">NoMoreiTunes extension</a> is probably a better way to do this.
</div>
<p>
I read somewhere that Safari (or the OS? or iTunes?) sometimes decides to &#8220;fix&#8221; the mappings of iTunes URL protocol handlers, forcing you to &#8220;play cat and mouse&#8221; if you decide to prevent iTunes from automagically opening up by removing it as the itms: protocol handler, so I decided that it would be best to try and fix this problem by messing with the iTunes website source via GlimmerBlocker, which I already was using for ad blocking.
</p>
<p>
I couldn&#8217;t find any straightforward directions on how to do this with GlimmerBlocker so I decided to post it here myself once I figured out how to do it. So this is how I prevented iTunes from automatically opening up whenever I open up a store link in my browser:
</p>
<ul>
<li>Open the GlimmerBlocker &#8220;filters&#8221; tab and <strong>add a new filter</strong>, as well as <strong>a new rule</strong> for this filter.</li>
<li>Select <strong>Whitelist URL, optionally modifying content</strong> as the action</li>
<li>For the <em>Host</em> section, select <strong>is</strong> as the predicate and type in <strong>itunes.apple.com</strong></li>
<li>Select <strong>ignored</strong> for both <em>Path</em> and <em>Query</em></li>
<li>Switch to the <strong>transform</strong> tab and type in the following:</li>
<div class="codecolorer-container javascript mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">replace<span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/detectAndOpenItunes\(\);/g</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;&lt;!-- detectAndOpenItunes() zapped --&gt;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></div>
<li>Make sure the <em>Only for content-type</em> selection in the bottom-right corner of the dialog sheet is <strong>html</strong></li>
<li>Save</li>
</ul>
<p>
This seems to correctly prevent the iTunes app from opening up whenever a store website is opened, but it still allows for opening the viewed product in the stand-alone app via the <em>&#8220;View in iTunes&#8221;</em> link on the page.</p>
]]></content:encoded>
			<wfw:commentRss>http://hasseg.org/blog/post/441/prevent-itunes-websites-from-opening-the-itunes-app-using-glimmerblocker/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Print AppleScript files with color-coding in the Terminal</title>
		<link>http://hasseg.org/blog/post/392/print-applescript-files-with-color-coding-in-the-terminal/</link>
		<comments>http://hasseg.org/blog/post/392/print-applescript-files-with-color-coding-in-the-terminal/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 17:37:53 +0000</pubDate>
		<dc:creator>Ali Rantakari</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://hasseg.org/blog/?p=392</guid>
		<description><![CDATA[Even though I curse and hate its syntax, I have to admit that AppleScript certainly provides one of the nicest things OS X has to offer in comparison to other operating systems: almost-ubiquitous scripting of GUI applications (one could argue that this is not due to the AppleScript language itself, but the Open Scripting Architecture [...]]]></description>
			<content:encoded><![CDATA[<p>
<img align="right" src="/asprint/appIcon.png" alt="asprint image" width="128" height="106" style="margin-left: 5px;" /> Even though I <em>curse and hate</em> its syntax, I have to admit that AppleScript certainly provides one of the nicest things OS X has to offer in comparison to other operating systems: almost-ubiquitous scripting of GUI applications (one could argue that this is not due to the AppleScript language itself, but the <a href="http://developer.apple.com/mac/library/documentation/AppleScript/Conceptual/AppleScriptX/Concepts/osa.html">Open Scripting Architecture</a> which AppleScript is simply a language for, but that&#8217;s just semantics). Recently I&#8217;ve had to work with AppleScript files a bit more than usual while implementing <a href="/tagger">Tagger</a>&#8216;s <em>front app scripts</em> feature, and I noticed that I often wanted to <strong>print out the contents of (compiled) AppleScript files</strong> in the Terminal. The built-in command <a href="http://developer.apple.com/mac/library/documentation/Darwin/Reference/ManPages/man1/osadecompile.1.html"><span style="font-family:monospace;">osadecompile</span></a> does just that: it reads in the AppleScript file, decompiles it, formats the code and nicely prints it out. I&#8217;m used to seeing my code with <strong>syntax highlighting</strong>, though, so I decided to write a small program that works similarly to <span style="font-family:monospace;">osadecompile</span> but uses ANSI escape sequences to format the output.
</p>
<p><span id="more-392"></span></p>
<p>
The <a href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ApplicationKit/Classes/NSAppleScript_AppKitAdditions/Reference/Reference.html#//apple_ref/occ/instm/NSAppleScript/richTextSource">Application Kit additions to the <span style="font-family:monospace;">NSAppleScript</span> class</a> provide an implementation of the syntax highlighting (which would be the hardest part in implementing something like this) and I already have the <a href="/ansiEscapeHelper"><span style="font-family:monospace;">ANSIEscapeHelper</span> class</a> that provides the translation of an <span style="font-family:monospace;">NSAttributedString</span> to an ANSI-escaped <span style="font-family:monospace;">NSString</span> (which would be the second-hardest part in implementing something like this) so writing a command-line program around these two parts was quite simple in the end. The program is called <strong><span style="font-family:monospace;">asprint</span></strong> and it has <a href="/asprint">its own page</a> on this site where you can download it.
</p>
<p>
This is what using <span style="font-family:monospace;">asprint</span> looks like:
</p>
<div align="center">
<img src="http://hasseg.org/blog/wp-content/uploaded/2010/03/asprint-screenshot.png" alt="asprint screenshot" width="445" height="592" />
</div></p>
]]></content:encoded>
			<wfw:commentRss>http://hasseg.org/blog/post/392/print-applescript-files-with-color-coding-in-the-terminal/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Quick, Declarative UML Sequence Diagrams</title>
		<link>http://hasseg.org/blog/post/329/quick-declarative-uml-sequence-diagrams/</link>
		<comments>http://hasseg.org/blog/post/329/quick-declarative-uml-sequence-diagrams/#comments</comments>
		<pubDate>Thu, 04 Jun 2009 13:34:55 +0000</pubDate>
		<dc:creator>Ali Rantakari</dc:creator>
				<category><![CDATA[jEdit]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://hasseg.org/blog/?p=329</guid>
		<description><![CDATA[I recently had to create a few UML sequence diagrams, and I decided that I didn&#8217;t want to spend too much time manually tweaking and fixing the diagrams themselves (which is what I probably would&#8217;ve done, had I used OmniGraffle or something similar), but instead focus on the content &#8212; the depicted workflow itself. This [...]]]></description>
			<content:encoded><![CDATA[<p>
<img align="right" src="http://hasseg.org/blog/wp-content/uploaded/2009/06/wsd-example-diagram-small.png" alt="wsd-example-diagram-small" width="113" height="86" /> I recently had to create a few UML sequence diagrams, and I decided that I didn&#8217;t want to spend too much time manually tweaking and fixing the diagrams themselves (which is what I probably would&#8217;ve done, had I used <em>OmniGraffle</em> or something similar), but instead <strong>focus on the <em>content</em></strong> &mdash; the depicted workflow itself. This is when I remembered the bookmark I had in my browser for the <strong><a href="http://www.websequencediagrams.com">Web Sequence Diagrams</a> online service</strong>.
</p>
<p><span id="more-329"></span></p>
<h2>Benefits of Declarative Diagramming</h2>
<p><em>Web Sequence Diagrams</em> is great. It uses <strong><a href="http://www.websequencediagrams.com/examples.html">a simple, readable syntax</a></strong> you can use to type in descriptions of sequential workflows and based on that it will <strong>generate the corresponding UML sequence diagrams</strong> for you.</p>
<p>
Working with these diagrams in this way has a couple of <strong>nice benefits</strong> over more intricate/professional methods:
</p>
<ul>
<li>They&#8217;re quick to create and quick to modify</li>
<li>The syntax is pretty easy to read as-is</li>
<li>The source is plain text, so all the benefits of using plain text apply (e.g. <em>can put under source control</em>, <em>can use simple diff tools</em>, <em>file sizes are small</em> etc.)</li>
</ul>
<h2>Helper Script and Syntax Highlighting</h2>
<p>
When I was sure I wanted to use this method again in the future, I hacked up a few quick and simple tools for this:
</p>
<h3>Script for generating the diagram images from source files</h3>
<p>At the time of this writing, there&#8217;s <a href="http://websequencediagrams.uservoice.com/pages/9445-general/suggestions/101931-create-a-command-line-version-of-this-application-">a suggestion called &#8220;Create a command-line version of this application&#8221;</a> on the service&#8217;s <em>UserVoice</em> site that&#8217;s labeled <em>&#8220;started&#8221;</em>, so hopefully in the future we&#8217;ll have a command-line sequence diagram generator from the author of the online service. In the meantime, though, here&#8217;s my solution. This is <strong>a Python script</strong> that can be used for generating the diagram images (using this service) from &#8220;source files&#8221; that contain the declarative workflow syntax. You just need to:</p>
<ol>
<li>type up your diagram description in a text editor and save it into a file</li>
<li>begin the first line in the file with <span style="font-family:monospace;">#wsd</span> (so that the script knows this is a websequencediagrams.com syntax file)</li>
<li><em>(optional:)</em> specify the <a href="http://www.websequencediagrams.com/embedding.html">diagram style</a> you&#8217;d like to use on the first line with the syntax <span style="font-family:monospace;">#wsd:style=modern-blue</span></li>
<li>call the script with the path to this file as an argument to generate the diagram image</li>
</ol>
<p>
The script uses a temporary <a href="http://www.sqlite.org/">SQLite</a> database to <strong>save hashes of file contents</strong> so that even if you call it repeatedly for the same file, it&#8217;ll notice if the file contents haven&#8217;t changed and decide not to send a request over to the server. I did this in order to reduce unnecessary load on the server. I tested the script on <strong>Mac OS 10.5.7, Windows XP SP3 and Ubuntu 9.04</strong> and it seems to work just fine on all of those (of course, on Windows you&#8217;ll first have to install <a href="http://www.python.org/download/">Python</a> manually).
</p>
<p><strong>Download</strong> the script here: <a href="/stuff/wsd/wsd.py">wsd.py</a></p>
<p>
Here&#8217;s an example on how to use it (to see the script&#8217;s <em>usage</em> info, run it without any arguments):
</p>
<p>Save this into a file called <em>ax-diagram</em>:</p>
<pre class="prettyprint">
#wsd

participant "Component A" as A
participant "Component X" as X

X -> A: what up
A -> A: processWhatUp()
note over A: A is confused
A -> X: go away
destroy X
</pre>
<p>Then run the script:</p>
<pre class="prettyprint">
wsd.py ax-diagram
</pre>
<p>
&#8230;and the file <em>ax-diagram.png</em> is created:
</p>
<p><img src="http://hasseg.org/blog/wp-content/uploaded/2009/06/wsd-example-diagram.png" alt="example diagram" width="323" height="247" /></p>
<h3>jEdit syntax highlighting mode</h3>
<p>This is a simple jEdit syntax highlighting mode for the Web Sequence Diagrams syntax. You can <strong>download</strong> the file here: <a href="/stuff/wsd/websequencediagrams.xml">websequencediagrams.xml</a>. Refer to <a href="?p=302">this other blog post of mine</a> for instructions on how to install modes for jEdit.</p>
<p>
Here&#8217;s a screenshot of the highlighted syntax on my machine:
</p>
<p><img src="http://hasseg.org/blog/wp-content/uploaded/2009/06/wsd-syntax.png" alt="websequencediagram.com syntax highlighting screenshot" width="249" height="166" /></p>
]]></content:encoded>
			<wfw:commentRss>http://hasseg.org/blog/post/329/quick-declarative-uml-sequence-diagrams/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>fcshctl: the Flex Compiler Shell Controller</title>
		<link>http://hasseg.org/blog/post/194/fcshctl-the-flex-compiler-shell-controller/</link>
		<comments>http://hasseg.org/blog/post/194/fcshctl-the-flex-compiler-shell-controller/#comments</comments>
		<pubDate>Mon, 03 Nov 2008 17:32:35 +0000</pubDate>
		<dc:creator>Ali Rantakari</dc:creator>
				<category><![CDATA[ActionScript 3]]></category>
		<category><![CDATA[Flex]]></category>
		<category><![CDATA[jEdit]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://hasseg.org/blog/?p=194</guid>
		<description><![CDATA[Introduction Like I&#8217;ve mentioned before in this blog, I develop Flex applications using the Flex SDK and jEdit instead of Adobe&#8217;s Flex Builder IDE. This setup has worked very well for me but one annoying issue I&#8217;ve had to deal with because of this is the slow compilation speed: every time I make a small [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>
Like I&#8217;ve mentioned before in this blog, I develop Flex applications using the Flex SDK and jEdit instead of Adobe&#8217;s Flex Builder IDE. This setup has worked very well for me but one annoying issue I&#8217;ve had to deal with because of this is <strong>the slow compilation speed</strong>: every time I make a small change into one of my projects and recompile it, the mxmlc compiler (that my build scripts are calling) has to load the JVM into memory and recompile my whole project from scratch, which obviously takes a while. Compiling things in Flex Builder is a lot faster, and the reason for that is <em><a href="http://labs.adobe.com/wiki/index.php/Flex_Compiler_Shell">the Flex Compiler Shell</a></em>, which it uses for compilation instead of mxmlc.
</p>
<div style="padding:4px;background:#eee;border:1px solid #ddd;">
<em><strong>Update (Version 0.5.1, Mar 17, 09):</strong></p>
<ul>
<li>Display a &#8220;compiling&#8230;&#8221; message before sending fcsh a compilation command in order to let the user know that something is going on and that they should wait instead of just killing the process.</li>
<li>If the log file exists when fcshctl runs, check if there are any other fcshctl instances running, and if not, assume that the log file has been orphaned, delete it and continue.</li>
<li>Exit with status code 0 (&#8220;ok&#8221;) if fcsh output ends in the <em>&#8220;Nothing has changed since the last compile&#8221;</em> message.</li>
</ul>
<p></em>
</div>
<p><span id="more-194"></span></p>
<div style="padding:4px;background:#eee;border:1px solid #ddd;">
<em><br />
<strong>Update (Version 0.5, Dec 10, 08):</strong></p>
<ul>
<li>Made it possible to specify a filename as the argument to the &#8220;clear&#8221; command &#8212; fcshctl will then try to find the first compile target id matching the specified filename and clear the corresponding id (example: &#8220;fcshctl clear MyApp.mxml&#8221;)</li>
<li>Made fcshctl find compile target ids corresponding to specific filenames or paths by asking fcsh directly via the &#8220;info&#8221; command instead of retaining them on its own in a temporary file (this is in order to avoid problems that could arise if this temp file and fcsh&#8217;s own list of retained compile target ids would get out of sync.)</li>
<li>Added command &#8220;id&#8221; which can be used to find the first compile target id matching a specified string (example: &#8220;fcshctl id MyApp.mxml&#8221;)</li>
</ul>
<p><strong>Update (Version 0.4, Nov 4, 08):</strong></p>
<ul>
<li>Made the script use only one logfile (i.e. one with a static path) and check its existence (and if it does exist, wait for it to be deleted) before continuing, so as to make sure no two fcshctl instances can try to send commands to fcsh at the same time, or before an already running command has finished executing and returned control to the prompt.</li>
</ul>
<p></em>
</div>
<p></p>
<p>
The basic idea behind the Flex Compiler Shell is that it would stay in memory between compilations (thus avoiding the cost of loading up the JVM every time you want to compile something) and use a technique called <strong>incremental compilation</strong> that, as the name suggests, is based on the idea of only compiling the parts of your project that have changed since the last compilation (thus making the process a lot faster). When you run the Flex Compiler Shell executable (called <em>fcsh</em>), you&#8217;re thrown into an interactive shell where you can run commands in order to compile your projects and control the operation of fcsh itself.
</p>
<h2>The Problem</h2>
<p>
When I found out about fcsh, tried it out and saw how much faster it was than mxmlc, of course I wanted to immediately start using it instead in my build scripts. The biggest problem with doing this, though, is the fact that <strong>the basic operation of these two programs is fundamentally different</strong>: when you run mxmlc, it compiles the project, prints some messages to standard output and then exits (with the exit status 0 if the compilation was successful or 1 if it wasn&#8217;t), which is perfect for integrating it into build scripts. Fcsh, on the other hand, throws you into a shell of its own and expects you to essentially operate it from within itself (instead of simply calling it with some arguments and then having it return with some standard output and an exit status like mxmlc).
</p>
<p>
The other issue that makes fcsh more difficult to use in general is that in order to use the incremental compilation feature, you have to first compile your project like you normally would (using the &#8220;mxmlc&#8221; command), then make note of the <em>&#8220;compile target id&#8221;</em> number that fcsh then assigns to this project and specifies in its output, and for future compilations use the &#8220;compile N&#8221; (where N is the compile target id) command.
</p>
<h2>The Solution</h2>
<p>
I tried to search for a solution to this problem that somebody else might have come up with but didn&#8217;t find an adequate one (a list of the ones that I could find is further down), so I decided to give it a shot myself. My approach, called <strong>fcshctl</strong> (short for &#8220;fcsh controller&#8221;), is basically a simple bash script that:</p>
<ol>
<li>starts the fcsh process if it isn&#8217;t already running</li>
<li>forwards its arguments to fcsh as commands</li>
<li>reads the output of that command from the fcsh interactive shell and prints it to the standard output</li>
<li>exits with status 0 (success) or >0 (failure)</li>
</ol>
<p>
In addition to this, I also made the script <strong>automatically and transparently invoke the incremental compilation feature</strong> whenever applicable so that I wouldn&#8217;t have to worry about keeping track of the compile target ids and using a different command for the compilation whenever one had already been assigned.
</p>
<p>
Below is a summarization of the pros and cons of this solution:
</p>
<h3>Pros:</h3>
<ul>
<li>It&#8217;s quite simple &#8212; just one shell script (a few others are included in the .zip that are only for convenience and not required)</li>
<li>It runs the fcsh instance in a <a href="http://www.gnu.org/software/screen/">GNU screen</a> session, which means that:</li>
<ul>
<li>The running fcsh instance is accessible to all user processes (i.e. not just within a single shell session, for example)</li>
<li>It is possible for the user to enter the running fcsh interactive shell at any time (by attaching to the screen session via the command <span style="font-family:monospace;">screen -r -S fcsh</span>) and manually interact with it</li>
</ul>
<li>It automatically checks whether you&#8217;ve compiled a specific file before and keeps track of the compile target ids that fcsh assigns so that it can automatically and transparently invoke the incremental compilation feature and let you access the speed gains that are fcsh&#8217;s main offering without any additional work. This feature can also be turned off by setting an environment variable.</li>
<li>A proxy script (called <span style="font-family:monospace;">fcshctl-mxmlc</span>) that can be used in place of mxmlc is provided. It simply calls fcshctl with <span style="font-family:monospace;">&#8220;mxmlc&#8221;</span> as the first argument, followed by all the other arguments you specify, so that you can simply use this script as a stand-in for mxmlc in any build scripts that you may be using without having to modify them any further.</li>
</ul>
<h3>Cons:</h3>
<ul>
<li>It uses the GNU screen logging mechanism and polling for changes in the log file in order to catch the output of commands sent to fcsh, which is not very elegant and causes a slowdown of maybe about a couple hundred milliseconds before the output is printed to stdout.</li>
<li>The output of the executed fcsh command is not printed to the standard output as it comes, but instead all at once when the command finishes (this is not a problem for me personally, but others might want to fix this).</li>
<li>It&#8217;s implemented as a bash script, which means that it&#8217;s not the fastest monster out there (we&#8217;re talking about milliseconds here, though, so it doesn&#8217;t bother me at all).</li>
</ul>
<h2>Download</h2>
<p>
You can download fcshctl here:</p>
<ul>
<li><strong><a href="/stuff/fcshctl/fcshctl-v0.5.1.zip">fcshctl-v0.5.1.zip</a> (latest)</strong></li>
<li><a href="/stuff/fcshctl/fcshctl-v0.5.zip">fcshctl-v0.5.zip</a></li>
<li><a href="/stuff/fcshctl/fcshctl-v0.4.zip">fcshctl-v0.4.zip</a></li>
<li><a href="/stuff/fcshctl/fcshctl-v0.3.zip">fcshctl-v0.3.zip</a></li>
</ul>
<p>
fcshctl has been tested with fcsh versions <em>3.0.0 build 477</em> and <em>3.1.0 build 2710</em> on Mac OS 10.5.5. It is licensed under <a href="http://hasseg.org/stuff/license/MIT_License.txt">the MIT License</a>.
</p>
<p>
The script requires the following to be in your <span style="font-family:monospace;">$PATH</span>: rm, mv, cat, ps, sleep, tail, head, grep, awk, screen, xargs and basename. <strong>You also need to have the <span style="font-family:monospace;">FLEX_HOME</span> environment variable set to point to the Flex SDK root path.</strong>
</p>
<h2>Example of use</h2>
<p><pre>
fcshctl $ export FLEX_HOME=/Users/username/code/SDKs/flex_sdk_3.1
fcshctl $
fcshctl $ ./fcshctl
<span style="color:blue;">
Usage: fcshctl &lt;commands&gt;

&nbsp;&nbsp;Substitute &lt;commands&gt; with any commands you
&nbsp;&nbsp;would like to send fcsh, just like you would
&nbsp;&nbsp;enter them in the interactive fcsh shell
&nbsp;&nbsp;session.

&nbsp;&nbsp;To get a list of the available commands, run:

&nbsp;&nbsp;&nbsp;&nbsp;fcshctl help
</span>
fcshctl $
fcshctl $ ./fcshctl help
<span style="color:blue;">List of fcsh commands:
mxmlc arg1 arg2 ...      full compilation and optimization; return a target id
compc arg1 arg2 ...      full SWC compilation
compile id               incremental compilation
clear [id]               clear target(s)
info [id]                display compile target info
quit                     quit</span>
fcshctl $
fcshctl $ ./fcshctl mxmlc ~/code/Flex/projects/testbed/testbed.mxml
<span style="color:blue;">Loading configuration file /Users/username/code/SDKs/flex_sdk_3.1/frameworks/flex-config.xml
Recompile: /Users/username/code/Flex/projects/testbed/testbed.mxml
Reason: The source file wasn't fully compiled.
Files changed: 0 Files affected: 1
/Users/username/code/Flex/projects/testbed/testbed.mxml(28):  Error: Incorrect number of arguments.  Expected 2.

&nbsp;&nbsp;&nbsp;&nbsp;func1("toka");
</span>
fcshctl $ echo $?
1
fcshctl $
fcshctl $
</pre>
</p>
<h2>Other similar solutions</h2>
<p>
Below is a list of other approaches to the problem of integrating fcsh to non-standard (i.e. non-Flex Builder) workflows (roughly in order from most promising to least promising), and short lists of reasons why I personally didn&#8217;t want to use them. If my solution doesn&#8217;t seem good to you, you should maybe check some of these out.
</p>
<p>
<a href="http://www.vim.org/scripts/script.php?script_id=1793">fcsh tools</a> by <em>Mike Rowe</em></p>
<ul>
<li>Runs fcsh in a daemonized process, which means you won&#8217;t be able to enter the interactive shell of a running fcsh process and manually interact with it</li>
<li>You can only specify the filename to compile; has no support for additional mxmlc arguments</li>
<li>For GNU/Linux (but seems to work just fine on OS X as well)</li>
</ul>
<p><a href="http://code.google.com/p/flex-compiler-shell-daemon/">flex-compiler-shell-daemon</a> by <em>Leonardo Soto Muños</em> (also see <a href="http://blog.leosoto.com/2008/10/flex-compiler-shell-daemon.html">his blog post about it</a>)</p>
<ul>
<li>I couldn&#8217;t get it to work out of the box on OS X</li>
<li>Runs fcsh in a daemonized process, which means you won&#8217;t be able to enter the interactive shell of a running fcsh process and manually interact with it</li>
</ul>
<p><a href="http://fcshwrapper.blogspot.com/">FCSH Wrapper</a> by <em>Mihai Vasilache</em></p>
<ul>
<li>For Windows</li>
<li>Designed to be used with Ant</li>
<li><a href="http://mihai.vasilache.googlepages.com/classDiagram.jpg">A bit complicated</a></li>
</ul>
<p><a href="http://code.google.com/p/fsch/">http://code.google.com/p/fsch/</a> by <em>nimrod97</em></p>
<ul>
<li>For Windows</li>
</ul>
<p><a href="http://zarkov.bigsource.de/front_content.php">BigSource Zarkov</a> by <em>BigSource GbR</em></p>
<ul>
<li>For Eclipse &#038; Ant</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://hasseg.org/blog/post/194/fcshctl-the-flex-compiler-shell-controller/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Gmail Backups with fetchmail on OS X</title>
		<link>http://hasseg.org/blog/post/161/gmail-backups-with-fetchmail-on-os-x/</link>
		<comments>http://hasseg.org/blog/post/161/gmail-backups-with-fetchmail-on-os-x/#comments</comments>
		<pubDate>Thu, 14 Aug 2008 11:32:13 +0000</pubDate>
		<dc:creator>Ali Rantakari</dc:creator>
				<category><![CDATA[Featured]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://hasseg.org/blog/?p=161</guid>
		<description><![CDATA[I use GMail as my personal email provider, and as much as I like the simple and snappy UI, the conversation views and the filtering and search possibilities, I&#8217;ve grown more and more worried about having all of my (important) mails stored on someone else&#8217;s servers. Now, out of all of the big IT companies [...]]]></description>
			<content:encoded><![CDATA[<p>
<img align="right" src="http://hasseg.org/blog/wp-content/uploaded/2008/08/gmail-backup.png" alt="" title="gmail-backup" width="130" height="124" /> I use GMail as my personal email provider, and as much as I like the simple and snappy UI, the conversation views and the filtering and search possibilities, I&#8217;ve grown more and more worried about having all of my (important) mails stored on someone else&#8217;s servers. Now, out of all of the big IT companies in the world I&#8217;d say I trust Google a heck of a lot more than anyone else, but this doesn&#8217;t mean that I shouldn&#8217;t take into consideration the possibility of something going wrong on their end and as a result some (or Bob forbid, <em>all</em>) of my mails disappearing into bit heaven.
</p>
<p>
The good news is that Google provides a nice, standard POP3 interface for downloading emails from their service, and all of the software required for downloading messages via POP is already installed in Mac OS X Leopard by default. Below I&#8217;ll go through all of the steps it took me to set up periodical and automated GMail backups on my Macbook.
</p>
<p><span id="more-161"></span></p>
<p>
The following were my sources for most of the information presented here:</p>
<ul>
<li><a href="http://lifehacker.com/software/gmail/geek-to-live--back-up-gmail-with-fetchmail-235207.php">LifeHacker: Geek to Live: Back up Gmail with fetchmail</a></li>
<li><a href="http://logicbound.blogspot.com/2007/10/backup-gmail-data.html">Logic Bound: Backup Gmail Data</a></li>
<li><a href="http://bronski.net/data/fetchmail-eng.php">bronski.net: fetchmail &amp; SSL</a></li>
<li><a href="http://lists.berlios.de/pipermail/fetchmail-users/2006-July/000488.html">Matthias Andree and Paul Elliott on [fetchmail-users]: What is a &#8220;local issuer certificate&#8221;?</a></li>
</ul>
<h3>Configure GMail for POP access</h3>
<ol>
<li>Go to GMail&#8217;s <em>&#8220;Forwarding and POP/IMAP&#8221;</em> settings</li>
<li>Set the <em>&#8220;POP access&#8221;</em> setting to <strong><em>&#8220;Enable POP for all mail (even mail that&#8217;s already been downloaded)&#8221;</em></strong></li>
<li>Make sure that the <em>&#8220;When messages are accessed with POP&#8221;</em> setting says <strong><em>&#8220;keep Gmail&#8217;s copy in the inbox&#8221;</em></strong></li>
</ol>
<h3>Configure fetchmail to Download the Messages</h3>
<ol>
<li>Create <span style="font-family:monospace;">~/.fetchmailrc</span> with the following contents (replacing GMAIL_USERNAME, GMAIL_PASSWORD and LOCAL_USERNAME with their real values in your case):</li>
<pre class="prettyprint">
poll pop.gmail.com with proto POP3 and options no dns
user 'GMAIL_USERNAME@gmail.com' there with password 'GMAIL_PASSWORD' is 'LOCAL_USERNAME' here and wants mda "/usr/bin/procmail -d %T"  options ssl keep sslcertck sslcertpath "/Users/LOCAL_USERNAME/.ssl/certs"
</pre>
<p>	This configuration basically tells fetchmail to:</p>
<ul>
<li>Connect to the GMail POP server using the POP3 protocol,</li>
<li>Map your GMail username to your localhost username,</li>
<li>Deliver the downloaded mail into your local system mailbox (mail spool file),</li>
<li>Connect using an encrypted SSL connection,</li>
<li>Strictly check the SSL certificates of the server it connects to against local trusted certificates,</li>
<li>Search for the local certificates in <span style="font-family:monospace;">~/.ssl/certs</span></li>
</ul>
<li>Set the proper rights for <span style="font-family:monospace;">~/.fetchmailrc</span>:</li>
<div class="codecolorer-container text mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; chmod 710 ~/.fetchmailrc</div></div>
<li>Get the pop.gmail.com server&#8217;s SSL certificate from the POP port <em>(note that this should be done using a secure, trusted internet connection &#8212; otherwise it kind of defeats the purpose)</em>:</li>
<div class="codecolorer-container text mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; openssl s_client -connect pop.gmail.com:995 -showcerts</div></div>
<p>From the output of this command, copy the part that looks like this:</p>
<div class="codecolorer-container bash mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #660033;">-----BEGIN</span> CERTIFICATE-----<br />
<span style="color: #7a0874; font-weight: bold;">&#40;</span>a big bunch of characters here<span style="color: #7a0874; font-weight: bold;">&#41;</span><br />
<span style="color: #660033;">-----END</span> CERTIFICATE-----</div></div>
<p>And save it into a file called <span style="font-family:monospace;">~/.ssl/certs/gmailpop.pem</span>.</p>
<li>Download the certificate authority (Equifax) root certificate (for example <a href="http://www.geotrust.com/resources/root_certificates/index.asp">from GeoTrust&#8217;s site here</a>, where it says <em>&#8220;Equifax Secure Certificate Authority (Base-64 encoded X.509)&#8221;</em>), rename it to &#8220;equifax.pem&#8221; and move it to <span style="font-family:monospace;">~/.ssl/certs/equifax.pem</span> <em>(and just like the previous step, this should be done over a trusted internet connection as well)</em>.</li>
<li>Hash the certificates in this directory by running:</li>
<div class="codecolorer-container text mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; c_rehash ~/.ssl/certs/</div></div>
</ol>
<h3>Optional: Specify the Location for Downloaded Messages</h3>
<p>
We&#8217;ve configured fetchmail to send messages to procmail, which will handle the storing of them in a <em>mail spool file</em>. By default this will be in <span style="font-family:monospace;">/var/mail/LOCAL_USERNAME</span>, but if you want to store it somewhere else, you can specify the location in the <span style="font-family:monospace;">~/.procmailrc</span> configuration file. Below is an example (replace LOCAL_USERNAME with your username):
</p>
<div class="codecolorer-container text mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">MAILDIR=&quot;$HOME/.mailspool&quot;<br />
DEFAULT=&quot;$HOME/.mailspool/LOCAL_USERNAME&quot;</div></div>
<p>
I prefer to exclude my mail spool file from Time Machine backups (because it&#8217;s a large file that changes very often which makes it take up a lot of disk space from my backup volume) so I have it located in <span style="font-family:monospace;">~/.mailspool/</span> like in the above example. This is because in OS X <span style="font-family:monospace;">/var</span> is actually a symbolic link to <span style="font-family:monospace;">/private/var</span> and Time Machine has a bug where it&#8217;s impossible to exclude anything from under that path from backups (for example, if I choose to exclude <span style="font-family:monospace;">/private/var/mail</span> in the GUI, it&#8217;ll replace this selection with <span style="font-family:monospace;">/var/mail</span> automatically, and even though <span style="font-family:monospace;">/var/mail</span> is then excluded, it&#8217;ll still back up <span style="font-family:monospace;">/private/var/mail</span>).
</p>
<h3>Download Messages with fetchmail</h3>
<p>
You can now download the mail by running this command (the -v argument is for verbose output):</p>
<div class="codecolorer-container text mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">fetchmail -v</div></div>
<p>Unless you only have a few mails in your Gmail box, this command will initially have to be run several times in a row in order to get all of the messages since it only downloads a few hundred messages at a time. The mail spool file containing all of the downloaded messages will then be found in <span style="font-family:monospace;">/var/mail/LOCAL_USERNAME</span> (or in whichever location you&#8217;ve specified in <span style="font-family:monospace;">~/.procmailrc</span>).
</p>
<p>
It&#8217;s a good idea to set up a launchd job for running this command between regular intervals so that you wouldn&#8217;t have to remember to manually do it yourself. <a href="http://lingon.sourceforge.net/">Lingon</a> is an ideal GUI app for this purpose. My GMail backup launchd job doesn&#8217;t call fetchmail directly, though: it calls this <a href="/stuff/gmailBackupScript/gmailBackupScript.zip">helper Python script</a> that I&#8217;ve written. The script does the following:</p>
<ul>
<li>Runs fetchmail,</li>
<li>Displays Growl messages about the result <em>(success or failure, number of messages downloaded if successful, etc.),</em></li>
<li>Optionally saves fetchmail&#8217;s output into a log file when done.</li>
</ul>
<p>Feel free to use it (remember to set the values in the &#8220;settings&#8221; section before running it, though).
</p>
<h3>Read Downloaded Messages with Thunderbird</h3>
<p>
In <a href="http://www.mozilla.com/en-US/thunderbird/">Mozilla Thunderbird</a>, go to <em>Tools > Account Settings&#8230; > Local Folders</em> to get to the <strong><em>Local directory</em></strong> path. Go into this directory and create a symbolic link there that points to the mail spool file:</p>
<div class="codecolorer-container bash mac-classic codecolorer-customstyle" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="bash codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #7a0874; font-weight: bold;">cd</span> PATH_COPIED_FROM_THUNDERBIRD<br />
<span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #000000; font-weight: bold;">/</span>var<span style="color: #000000; font-weight: bold;">/</span>mail<span style="color: #000000; font-weight: bold;">/</span>LOCAL_USERNAME .<span style="color: #000000; font-weight: bold;">/</span>GMailBackups</div></div>
<p>After this you&#8217;ll be able to find your backed up GMail messages in a folder called &#8220;GMailBackups&#8221; under &#8220;Local Folders&#8221; in Thunderbird.
</p>
<div style="height:30px;">&nbsp;</div>
]]></content:encoded>
			<wfw:commentRss>http://hasseg.org/blog/post/161/gmail-backups-with-fetchmail-on-os-x/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Automatic, Periodic Syncing with iSync</title>
		<link>http://hasseg.org/blog/post/136/automatic-periodic-syncing-with-isync/</link>
		<comments>http://hasseg.org/blog/post/136/automatic-periodic-syncing-with-isync/#comments</comments>
		<pubDate>Thu, 17 Apr 2008 14:02:03 +0000</pubDate>
		<dc:creator>Ali Rantakari</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://hasseg.org/blog/?p=136</guid>
		<description><![CDATA[The first time I decided I wanted to start synchronizing my cell phone&#8217;s calendar and address book with my Mac&#8217;s, I noticed how iSync doesn&#8217;t have a system of automatically invoking the synchronization procedure between regular intervals. I wanted to have the sync invoked automatically every 30 minutes, so I figured I had to do [...]]]></description>
			<content:encoded><![CDATA[<p>
<img align="right" src='http://hasseg.org/blog/wp-content/uploaded/2008/04/synccompleted.png' alt='Sync completed successfully Growl notification' /> The first time I decided I wanted to start synchronizing my cell phone&#8217;s calendar and address book with my Mac&#8217;s, I noticed how iSync doesn&#8217;t have a system of automatically invoking the synchronization procedure between regular intervals. I wanted to have the sync invoked automatically every 30 minutes, so I figured I had to do it myself somehow. I&#8217;ve had this script in place and running for, I don&#8217;t know, a year and a half now, and I&#8217;ve used it with two different phones (the Nokia 3230 and the Nokia N82.) I&#8217;m not sure why I haven&#8217;t blogged about it before, since this is exactly the kind of stuff I tend to write about here. Probably I&#8217;ve just forgotten is all. In any case, here it is.
</p>
<p><span id="more-136"></span></p>
<p>
Marc Liyanage at entropy.ch has already <a href="http://www.entropy.ch/blog/Mac+OS+X/2006/07/04/Periodically-Run-iSync-if-Mobile-Phone-is-in-Bluetooth-Range.html">pretty much done the bulk of the work for this</a> already. The differences between my solution and his are basically that mine tries to output lots of info to the user (via stdout or Growl,) mine doesn&#8217;t care when the last sync took place, and that mine can be configured to start up iSync if it isn&#8217;t already running.
</p>
<p>
An earlier version of my script figured out (via iSync&#8217;s AppleScript interface) when the last sync procedure took place (regardless of whether it had been invoked from this script or from iSync itself) and then either cancelled or proceeded with the syncing based on that, but after a while I realized I had no need for that kind of a feature, so I removed it. I don&#8217;t have the old version available anymore, but if anyone is interested in adding that feature, I still have the <em>lastSync.scpt</em> AppleScript I used to check if the difference between the current date and the last sync&#8217;s date was long enough. It&#8217;s included in the zip archive (a link to which is below.)
</p>
<p>
The (very general) directions to configuring the script and making it run are in the comments in the beginning of the file.
</p>
<p>
Download:</p>
<ul>
<li><a href="/stuff/forceSyncScript/forceSyncScript.zip">The script and supporting files in a zip archive</a></li>
<li><a href="http://will.harris.ch/bluelist.gz">bluelist</a> by Marc Liyanage and Will Harris (required for this to work &#8212; save it in <em>/usr/local/bin</em> or somewhere)</li>
<li><a href="http://lingon.sourceforge.net/">Lingon</a> by Peter Borg (optional: for setting up a launchd configuration for this from a GUI)</li>
<li><a href="http://growl.info">Growl</a> (optional: for notifications. also remember to install the <em>growlnotify</em> CLI app that is included with the distribution package, and if you&#8217;re running Leopard, check out <a href="?p=111">my workaround for a Leopard bug in growlnotify</a>)</li>
</ul>
<p>
The script:</p>
<pre class="prettyprint">
#!/bin/bash

#
# ----------------------------------------------------------------
#
# DESCRIPTION:
#
# A script that is meant to be run periodically in order to
# force iSync to synchronize.
#
# It will not, however, invoke the sync if a specific
# device (e.g. a mobile phone) is not connected via Bluetooth.
#
#
#
# (c) Ali Rantakari, 2007-2008
#     http://hasseg.org
#
# ----------------------------------------------------------------
#
# REQUIRES:
#
# - OS X 10.4 (Tiger) or later
#
# - The "bluelist" helper application by Marc Liyanage
#   and Will Harris
#		( link to the blog post where i found it:
#		  http://tinyurl.com/2ahpme
#		  direct link to the app itself:
#		  http://will.harris.ch/bluelist.gz )
#
#
# OPTIONAL:
#
# - Growl + growlnotify (for notifications)
#
# - Lingon (launchd/launchctl GUI for scheduling the running
#           of this script at regular intervals)
#
#
# ----------------------------------------------------------------
#
# SETTING IT UP:
#
# 1) Change the settings in the "settings" area below to
#    correspond to your environment
#
# 2) Use Lingon/launchctl to schedule this script to be run
#    periodically
#
#
# ----------------------------------------------------------------
#
# NOTE 1:	You can run this script from the command line
#			with the parameter "-v" to check that it is working.
#			all notifications (and some additional info) will
#			be printed to the standard output then.
#
# NOTE 2:	I also noticed that iSync seems to not be setting the
# 			sync status value for applescript properly -
# 			a failed sync may have a status code of a successful
# 			one - and thus this script may notify you that
# 			the sync was successful when it in fact was not.
# 			I have reported this issue to Apple on 12 Feb 2008,
#           and as of this writing (17 Apr 2008,) it still seems
#           to be open (the radar ID is 5738357).
#
# NOTE 3:	I found a lot of useful info for making this
# 			script from these places:
#
# 			http://hollington.ca/technocrat/?p=44
# 			http://tinyurl.com/2ahpme  [ -> entropy.ch]
#
# ----------------------------------------------------------------
# 

# get the location of this script.
#
# do not change this (unless you know a better
# implementation ;) )
#
DN=`dirname $0`
THISDIR="`cd $DN; pwd`"

# ----------------------------------------------------------------
#
# SETTINGS:
#
# 

# the bluetooth name of your mobile phone (or any similar device
# you're syncing with iSync via BT)
#
MOBILEBTNAME="MyPhoneName"

# the level of notifications you want to receive
#
# 0 = quiet (no notifications at all)
# 1 = inform only when starting to sync and
#     when sync has completed
# 2 = inform of everything
#
NOTIFICATIONLEVEL=1

# whether to run iSync if it isn't already running
#
# "true"  =		if iSync is not running, run it
# 				and then invoke the sync procedure
# "false" =  	if iSync is not running, don't sync
#
RUNISYNCIFNOTRUNNING="false"

# locations of CLI apps used
#
# custom: (you need to get these yourself)
#
GROWLNOTIFY=/usr/local/bin/growlnotify
BLUELIST=/usr/local/bin/bluelist
#
# system: (these should be here)
#
OSASCRIPT=/usr/bin/osascript
STAT=/usr/bin/stat
TOUCH=/usr/bin/touch

# the name of this application
# (to send to growlnotify)
#
THISAPP="Autosync script"

# whether to use growl or stdout (or both) for notifications
#
# "stdout" -> notifications will be printed to stdout
# "growl"  -> notifications will be sent to growl
# "both"   -> notifications will be sent to growl _and_
#             printed to stdout
#
NOTIFICATIONS="growl"

# the icon to show in growl notifications
#
GROWLICON="$THISDIR/forcesync.icon.png"

# - - - - - - - - - - - - - - - - - - - - - -
# settings end here.
# ----------------------------------------------------------------
# 

# Script IMPLEMENTATION begins here ---------------------------
# -------------------------------------------------------------
# 

# --- functions ------

# parameters:
#
# $1 = Title
# $2 = Message
# $3 = Minimum notification level
# $4 = Location of icon to show
show_message()
{
	if [ $NOTIFICATIONLEVEL -gt $(( $3 - 1 )) ] || [ $VERBOSEMODE == 1 ];then 

		if [ "$NOTIFICATIONS" != "stdout" ]; then

			if [ -e "$4" ];then
				THISGROWLICON="$4"
			else
				THISGROWLICON="$GROWLICON"
			fi

			$GROWLNOTIFY -n "$THISAPP" -t "$1" -m "$2" --image "$THISGROWLICON"

		fi

		if [ "$NOTIFICATIONS" != "growl" ];then

			echo "** $1"
			echo "   $2"
			echo " "

		fi

	fi
}

# no params
check_isync_running()
{
	if [ "`ps xwww | grep -v grep | grep -c iSync.app/Contents/MacOS/iSync`" == "0" ];then
		echo "false"
	else
		echo "true"
	fi
}

# no params
check_mobile_present()
{
	if [ "`$BLUELIST | grep \"$MOBILEBTNAME\"`" == "$MOBILEBTNAME" ];then
		echo "true"
	else
		echo "false"
	fi
}

# no params
activate_isync()
{
	$OSASCRIPT -e "tell application \"iSync\" to activate" -s o
}

# no params
hide_isync()
{
	$OSASCRIPT -e "tell application \"System Events\" to set visible of process \"iSync\" to false" -s o
}

# --- /functions ------

# script runs from here:
# --------------------------------------------

VERBOSEMODE=0
if [ "$1" == "-v" ];then
	VERBOSEMODE=1
	NOTIFICATIONS="both"
	echo " "
fi

# check if mobile phone is in Bluetooth range

if [ $VERBOSEMODE == 1 ];then
	echo " "
	echo -n "Scanning for bluetooth device \"$MOBILEBTNAME\"..."
fi

if [ "`check_mobile_present`" == "false" ];then
	if [ $VERBOSEMODE == 1 ];then
		echo " ...not found!"
		echo " "
	fi
	show_message "Will not sync" "\"$MOBILEBTNAME\" not found (either BT is off or device is out of range)" 2
	exit 0
else
	if [ $VERBOSEMODE == 1 ];then
		echo " ...found!"
		echo " "
	fi
fi

# check if iSync is running

ISYNCRUNNING="`check_isync_running`"

if [ "$ISYNCRUNNING" == "false" ] &#038;&#038; [ "$RUNISYNCIFNOTRUNNING" == "true" ];then

	show_message "Starting up iSync" "Activating and hiding iSync" 2
	activate_isync
	hide_isync

elif [ "$ISYNCRUNNING" == "false" ] &#038;&#038; [ "$RUNISYNCIFNOTRUNNING" != "true" ];then

	show_message "Will not sync" "iSync is not running" 2
	exit 0

elif [ "$ISYNCRUNNING" == "true" ];then
	if [ $VERBOSEMODE == 1 ];then
		echo "iSync seems to be running. continuing..."
		echo " "
	fi
else
	show_message "Error" "The iSyncRunning applescript returned invalid value: \"$ISYNCRUNNING\"" 1
	exit 0
fi

# sync

show_message "Sync starting" "Telling iSync to synchronize..." 1

SYNCSTATUS="`$OSASCRIPT -s o \"$THISDIR/forceSync.scpt\"`"

if [ "$SYNCSTATUS" == "2" ];then
	show_message "Sync completed" "...Synchronization completed successfully." 1
	exit 0
elif [ "$SYNCSTATUS" == "3" ];then
	show_message "Sync warnings" "...Synchronization completed with warnings!" 1
	exit 3
elif [ "$SYNCSTATUS" == "4" ];then
	show_message "Sync errors" "...Synchronization completed with errors!" 1
	exit 4
elif [ "$SYNCSTATUS" == "5" ];then
	show_message "Sync cancelled" "...Synchronization was cancelled!" 1
	exit 5
elif [ "$SYNCSTATUS" == "6" ];then
	show_message "Sync failed" "...Synchronization failed to complete!" 1
	exit 6
elif [ "$SYNCSTATUS" == "7" ];then
	show_message "Sync failed" "...Synchronization did not succeed (status: (7) \"never synced\")!" 1
	exit 7
else
	show_message "Sync error" "...Undefined error with sync: \"$SYNCSTATUS\"" 1
	exit 127
fi
</pre>
]]></content:encoded>
			<wfw:commentRss>http://hasseg.org/blog/post/136/automatic-periodic-syncing-with-isync/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Going Back to the Origin of a Downloaded File</title>
		<link>http://hasseg.org/blog/post/132/going-back-to-the-origin-of-a-downloaded-file/</link>
		<comments>http://hasseg.org/blog/post/132/going-back-to-the-origin-of-a-downloaded-file/#comments</comments>
		<pubDate>Fri, 21 Mar 2008 00:18:28 +0000</pubDate>
		<dc:creator>Ali Rantakari</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Scripts]]></category>

		<guid isPermaLink="false">http://hasseg.org/blog/?p=132</guid>
		<description><![CDATA[One of the biggest reasons why I prefer to use Safari as my web browser of choice on OS X is its integration with the rest of the operating system, a quite recent example of which is the tagging of downloaded files with Spotlight metadata about the location where they were downloaded from. In the [...]]]></description>
			<content:encoded><![CDATA[<p>
<img align="right" src='http://hasseg.org/blog/wp-content/uploaded/2008/03/gotosource-icon.png' alt='goToSource icon' /> One of the biggest reasons why I prefer to use Safari as my web browser of choice on OS X is its integration with the rest of the operating system, a quite recent example of which is the tagging of downloaded files with Spotlight metadata about the location where they were downloaded from. In the latest Safari update – version 3.1 – this was extended to also apply to pictures dragged from the browser onto the local filesystem.
</p>
<p>
This metadata is most frequently used in the dialogs that are shown whenever an executable is being opened for the first time after being downloaded from the web, and it is accessible to users via the &#8220;get info&#8221; dialog box. If you have a file laying around somewhere, and you&#8217;re trying to remember where you got it from, you can always look at the file info, find the &#8220;where from:&#8221; field, copy the address, switch to your browser, paste the address to the location bar, and press enter in order to get to the origin site. I knew you could read file metadata in OS X with the <em>mdls</em> utility, so I figured it&#8217;d be quite simple to make a little &#8220;droplet&#8221; application for streamlining the task of navigating to the origin web site of a particular file, so that&#8217;s exactly what I did.
</p>
<p><span id="more-132"></span></p>
<p>
To use the application, simply drag and drop any file on top of it. If the file has a metadata field about the location where it was downloaded from, that address will be opened in your default web browser. If there are several locations listed in the metadata, a dialog box will pop up to ask you to choose which one to navigate to. It will also confirm whether to go to the address or not if it looks like it&#8217;s a direct link to download the file itself.
</p>
<p>
The links to download the application and/or its source code are below. It is basically a Python script made into an application with <a href="http://www.sveinbjorn.org/platypus">Platypus</a>, and it&#8217;s using <a href="http://cocoadialog.sourceforge.net/">CocoaDialog</a> for the popup dialogs.
</p>
<p>
<img align="left" src='http://hasseg.org/blog/wp-content/uploaded/2008/03/gotosource-icon.png' alt='goToSource icon' />
<ul>
<li><a href="/stuff/goToSource/goToSource-v1.0.dmg">goToSource v1.0</a></li>
<li><a href="/stuff/goToSource/goToSource-src.zip">goToSource v1.0 source code</a></li>
</ul>
<div style="height:50px;">&nbsp;</div>
]]></content:encoded>
			<wfw:commentRss>http://hasseg.org/blog/post/132/going-back-to-the-origin-of-a-downloaded-file/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

