<?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>Brett Terpstraservice - Brett Terpstra</title>
	<atom:link href="http://brettterpstra.com/tag/service/feed/" rel="self" type="application/rss+xml" />
	<link>http://brettterpstra.com</link>
	<description>Elegant solutions to complex problems.</description>
	<lastBuildDate>Thu, 09 Feb 2012 15:01:27 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>A Service for writing MultiMarkdown footnotes inline</title>
		<link>http://brettterpstra.com/a-service-for-writing-multimarkdown-footnotes-inline/</link>
		<comments>http://brettterpstra.com/a-service-for-writing-multimarkdown-footnotes-inline/#comments</comments>
		<pubDate>Tue, 24 Jan 2012 16:52:39 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[multimarkdown]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3576</guid>
		<description><![CDATA[<p>This post should have been titled “What happens to my mornings.” I get a lot of one-off requests for scripts and tips on how to handle tasks specific to people’s workflow or writing style. I generally keep myself pretty busy, so I usually reply with a quick idea or thought and leave it up to them to run with it.&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/a-service-for-writing-multimarkdown-footnotes-inline/">A Service for writing MultiMarkdown footnotes inline</a></p>]]></description>
			<content:encoded><![CDATA[<p>This post should have been titled “What happens to my mornings.”</p>

<p>I get a lot of one-off requests for scripts and tips on how to handle tasks specific to people’s workflow or writing style. I generally keep myself pretty busy, so I usually reply with a quick idea or thought and leave it up to them to run with it. <a href="http://havecamerawilltravel.com/">David Coleman</a> emailed me this morning, though, with a request that struck me as an interesting enough idea to whip up a script before work.</p>

<p>What David wanted to do was take the idea behind my “Inline Links to References” command in the <a href="http://brettterpstra.com/project/markdown-service-tools/">Markdown Service Tools</a> and do something similar for footnotes, allowing him to write footnotes inline in a paragraph and have them converted before processing with MultiMarkdown. It’s not such a chore to skip a few lines and drop in the footnote syntax that this should be part of the spec, but it <em>is</em> something I would find handy in several situations. So…</p>

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

<p>The format I picked uses a syntax like this to denote a footnote:</p>

<pre><code>This is the regular text(*This is the footnote*), and you can drop the footnote in at any point.
</code></pre>

<p>The Service can handle footnotes inside of lines, at the end of lines, spanning multiple lines with breaks (creates paragraphs) and does fine with Markdown <em>within</em> the footnote. One nice thing about this syntax is that–if you’re previewing as you write–it italicizes the output to differentiate it until you’ve used the service to move it out of the main text.</p>

<p>Multi-line footnotes need to begin at the end of a line of text, and just use double-newlines to separate paragraphs within the footnote, e.g.:</p>

<pre><code>...the end of the paragraph. (*This is a footnote

which is going to span

more than one line*)
</code></pre>

<p>Here’s the script, also available as a Service download at the end of the post.</p>

<p><strong>Update:</strong> I just added a fix (in code below and the Service download) for making sure that footnote reference titles aren’t duplicated if you have existing MultiMarkdown-formatted footnotes in the document.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby"><span class="co1">#!/usr/bin/env ruby</span>
&nbsp;
<span class="kw1">def</span> e_sh<span class="br0">&#40;</span>str<span class="br0">&#41;</span>
	str.<span class="me1">to_s</span>.<span class="kw3">gsub</span><span class="br0">&#40;</span><span class="sy0">/</span><span class="br0">&#40;</span>?=<span class="br0">&#91;</span>^a<span class="sy0">-</span>zA<span class="sy0">-</span>Z0<span class="sy0">-</span><span class="nu0">9</span>_.\<span class="sy0">/</span>\<span class="sy0">-</span>\x7F<span class="sy0">-</span>\xFF\n<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">/</span>n, <span class="st0">'<span class="es0">\\</span>'</span><span class="br0">&#41;</span>
<span class="kw1">end</span>
&nbsp;
input = STDIN.<span class="me1">read</span>
&nbsp;
footnotes = input.<span class="me1">scan</span><span class="br0">&#40;</span><span class="sy0">/</span>\<span class="br0">&#40;</span>\<span class="sy0">*</span><span class="br0">&#40;</span>.<span class="sy0">*</span>?<span class="br0">&#41;</span>\<span class="sy0">*</span>\<span class="br0">&#41;</span><span class="sy0">/</span>m<span class="br0">&#41;</span>
existing = input.<span class="me1">scan</span><span class="br0">&#40;</span><span class="sy0">/</span>^\<span class="br0">&#91;</span>\^fn<span class="br0">&#40;</span>\d<span class="sy0">+</span><span class="br0">&#41;</span>\<span class="br0">&#93;</span>: <span class="sy0">/</span>i<span class="br0">&#41;</span>
counter = existing.<span class="me1">empty</span>? ? <span class="nu0">1</span> : existing.<span class="me1">uniq</span>.<span class="me1">sort</span><span class="br0">&#91;</span><span class="sy0">-</span><span class="nu0">1</span><span class="br0">&#93;</span>.<span class="me1">join</span>.<span class="me1">to_i</span> <span class="sy0">+</span> <span class="nu0">1</span>
&nbsp;
output = <span class="br0">&#91;</span><span class="br0">&#93;</span>
footnotes.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>note<span class="sy0">|</span> 
	output <span class="sy0">&lt;&lt;</span> <span class="br0">&#123;</span><span class="st0">'orig'</span> <span class="sy0">=&gt;</span> note<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>, <span class="st0">'title'</span> <span class="sy0">=&gt;</span> <span class="st0">&quot;fn#{counter}&quot;</span>, <span class="st0">'footnote'</span> <span class="sy0">=&gt;</span> note<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> <span class="br0">&#125;</span>
	counter <span class="sy0">+</span>= <span class="nu0">1</span>
<span class="br0">&#125;</span>
&nbsp;
o = <span class="br0">&#91;</span><span class="br0">&#93;</span>
output.<span class="me1">each_with_index</span> <span class="br0">&#123;</span> <span class="sy0">|</span>x,i<span class="sy0">|</span> 
	o.<span class="me1">push</span><span class="br0">&#40;</span><span class="st0">&quot;[^#{x['title']}]: #{x['footnote'].gsub(/<span class="es0">\n</span><span class="es0">\n</span>(<span class="es0">\s</span>*.)/,&quot;</span>\n\n\t\\<span class="nu0">1</span><span class="st0">&quot;)}&quot;</span><span class="br0">&#41;</span>
	input.<span class="kw3">gsub!</span><span class="br0">&#40;</span><span class="sy0">/</span>\<span class="br0">&#40;</span>\<span class="sy0">*</span><span class="co1">#{e_sh x['orig']}\*\)/m,&quot;[^#{x['title']}]&quot;)</span>
<span class="br0">&#125;</span>
<span class="kw3">puts</span> input.<span class="me1">strip</span> <span class="sy0">+</span> <span class="st0">&quot;<span class="es0">\n</span><span class="es0">\n</span>#{o.join(&quot;</span>\n\n<span class="st0">&quot;)}<span class="es0">\n</span>&quot;</span></pre></div></div>


<p>I’m in San Francisco for an AOL Tech code jam right now, so I don’t have a lot of time to thoroughly test this. Please let me know about any bugs that need fixing.</p>

<p>If you’re in San Francisco and like coffee or beer, hit me up <a href="http://twitter.com/ttscoff">on Twitter</a>. If you’re here for Macworld, then you’d better be at my <a href="http://www.macworldiworld.com/techtalks/thursday-overview/thursday-agenda/#903">“40 Tips in 40 Minutes”</a> talk with David Sparks and Merlin Mann on Thursday!</p>

<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/ConvertInlineFootnotesService1.21.zip?9d7bd4" title="Download Convert Inline Footnotes Service (68)"><img src="http://brettterpstra.com/wp-content/plugins/download-monitor/page-addon/thumbnail.gif?9d7bd4" alt="download image for Convert Inline Footnotes Service" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/ConvertInlineFootnotesService1.21.zip?9d7bd4" title="Download Convert Inline Footnotes Service (68)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/ConvertInlineFootnotesService1.21.zip?9d7bd4" title="Download Convert Inline Footnotes Service (68)">Convert Inline Footnotes Service</a> — Convert inline footnotes in ‘(*Footnote to be created*)‘ format to MultiMarkdown footnotes. <a href="http://brettterpstra.com/a-service-for-writing-multimarkdown-footnotes-inline">More Info</a></p></div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/a-better-os-x-system-service-for-evernote-notes-with-multimarkdown/' rel='bookmark' title='A better System Service for Evernote clipping — with MultiMarkdown'>A better System Service for Evernote clipping — with MultiMarkdown</a></li>
<li><a href='http://brettterpstra.com/auto-convert-your-inline-markdown-links-to-references/' rel='bookmark' title='Auto-convert your inline Markdown links to references'>Auto-convert your inline Markdown links to references</a></li>
<li><a href='http://brettterpstra.com/a-system-service-for-to-url-shortening/' rel='bookmark' title='A System Service for to. url shortening'>A System Service for to. url shortening</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/a-service-for-writing-multimarkdown-footnotes-inline/">A Service for writing MultiMarkdown footnotes inline</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/a-service-for-writing-multimarkdown-footnotes-inline/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>System Service: Clip to Day One</title>
		<link>http://brettterpstra.com/system-service-clip-to-day-one/</link>
		<comments>http://brettterpstra.com/system-service-clip-to-day-one/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 22:53:25 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3555</guid>
		<description><![CDATA[<p>I’m enjoying logging with Day One right now, and getting geeky with it. To that end, I put this project together during the few breaks I’ve had over the last couple of days leading up to the new Engadget live blog launch today1. The result is a practical proof of concept in the form of a System Service for clipping&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/system-service-clip-to-day-one/">System Service: Clip to Day One</a></p>]]></description>
			<content:encoded><![CDATA[<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  src="http://cdn2.brettterpstra.com/wp-content/uploads/2012/01/dayoneautomator.jpg?9d7bd4" alt="" title="dayoneautomator" width="250" height="243" class="alignright size-full wp-image-3556" />I’m enjoying logging with <a href="http://dayoneapp.com/">Day One</a> right now, and <a href="http://brettterpstra.com/logging-with-day-one-geek-style/">getting geeky with it</a>. To that end, I put this project together during the few breaks I’ve had over the last couple of days leading up to the new <a href="http://www.engadget.com/">Engadget</a> live blog launch today<sup id="fnref:lb"><a href="#fn:lb" rel="footnote">1</a></sup>. The result is a practical proof of concept in the form of a System Service for clipping any text to Day One. I figured that this could actually be really handy for more people than just me, so here it is.</p>

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

<p>Dayone uses a very simple XML format in separate files to store your entries. It’s easy to replicate the structure using a script, allowing you to directly generating your own Day One entries from any part of your workflow. I’m bypassing the <code>dayone</code> CLI and dropping the updates in directly for added flexibility. Don’t get me wrong, I absolutely <em>love</em> that Day One comes with a CLI, I just wanted to experiment around it.</p>

<p>I’m using the new iCloud support for sync, and this Service is built to work with that folder structure by default. The version below (and in the download) looks in “~/Library/Mobile Documents/” (where iCloud stores documents) for a folder containing the word “dayoneapp.” I don’t know offhand what the bizarre names of the folders indicate, but they differ between accounts, so we have to grep out the matching folder. Assuming your Journal is called Journal_dayone (default) and you’re using iCloud, you shouldn’t have to edit anything. If it doesn’t work, run this in Terminal and copy the resulting path into the “dayonepath” variable:</p>

<pre><code>find ~/Library/Mobile\ Documents/ -name "Journal_dayone"
</code></pre>

<p>If you’re using Dropbox, you’ll just need to make a minor alteration to the “dayonepath” variable. Delete the line starting with “dayonedir” and hardcode the Unix (POSIX) path to the “entries” folder, located directly inside of the Journal.dayone bundle in your Dropbox root folder. It will most likely be <code>/Users/[yourusername]/Dropbox/Journal.dayone/entries/</code> if you haven’t changed any defaults in Dropbox or Day One.</p>

<p>The service itself is available for download at the end of the post, or you can take the script below and home-roll your own in Automator. It should work out of the box, no need for ruby gems or symlinked CLIs.</p>

<p>The only configuration you <em>may</em> want to edit is the “starred” variable. This defaults to off because Services aren’t interactive and you probably don’t want to star <em>every</em> entry you clip. If you <em>do</em>, though, just change “starred = false” to “starred = true” and it will make your calendar look like a planetarium.</p>

<p>The Service will use <code>/usr/bin/textutil</code> to strip out any rich text artifacts. I’m not certain this is necessary, but I found that when clipping rich text I would lose all of my line breaks and indents. This seems to solve it. The script also looks for text with hard breaks and handles them Github-style, preserving breaks using Markdown line break syntax.</p>

<p>If you have <a href="http://growl.info">Growl</a> running, you’ll get a notification. To be polite, it checks for Growl before attempting any notifications. The check can be slow sometimes, though, so you may want to either remove the check if you always have Growl running, or remove the whole Growl section at the end if you don’t.</p>

<h3>The script:</h3>

<p>Here’s the script. The same script can be found in the Service download at the end by opening the .workflow file in Automator. You can easily customize/edit from there, so this is posted just for reference.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby">require 'time'
require 'erb'
&nbsp;
def e_sh(str)
	str.to_s.gsub(/(?=[^a-zA-Z0-9_.\/\-\x7F-\xFF\n])/n, '\\').gsub(/\n/, &quot;'\n'&quot;).sub(/^$/, &quot;''&quot;)
end
&nbsp;
input = STDIN.read
entrytext = %x{echo #{e_sh input}|textutil -stdin -convert txt -stdout}
entrytext.gsub!(/\n([^\n])/,&quot;    \n\\1&quot;)
uuid = %x{uuidgen}.gsub(/-/,'').strip
datestamp = Time.now.utc.iso8601
starred = false
&nbsp;
dayonedir = %x{ls ~/Library/Mobile\\ Documents/|grep dayoneapp}.strip
dayonepath = &quot;~/Library/Mobile\ Documents/#{dayonedir}/Documents/Journal_dayone/entries/&quot;
&nbsp;
template = ERB.new &lt;&lt;-XMLTEMPLATE
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;!DOCTYPE plist PUBLIC &quot;-//Apple//DTD PLIST 1.0//EN&quot; &quot;http://www.apple.com/DTDs/PropertyList-1.0.dtd&quot;&gt;
&lt;plist version=&quot;1.0&quot;&gt;
&lt;dict&gt;
	&lt;key&gt;Creation Date&lt;/key&gt;
	&lt;date&gt;<span class="sy0">&lt;%</span>= datestamp <span class="sy0">%&gt;</span>&lt;/date&gt;
	&lt;key&gt;Entry Text&lt;/key&gt;
	&lt;string&gt;&lt;![CDATA[<span class="sy0">&lt;%</span>= entrytext <span class="sy0">%&gt;</span>]]&gt;&lt;/string&gt;
	&lt;key&gt;Starred&lt;/key&gt;
	&lt;<span class="sy0">&lt;%</span>= starred <span class="sy0">%&gt;</span>/&gt;
	&lt;key&gt;UUID&lt;/key&gt;
	&lt;string&gt;<span class="sy0">&lt;%</span>= uuid <span class="sy0">%&gt;</span>&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
XMLTEMPLATE
&nbsp;
fh = File.new(File.expand_path(dayonepath+uuid+&quot;.doentry&quot;),'w+')
fh.puts template.result(binding)
fh.close
&nbsp;
growl_running = %x{osascript -e 'tell application &quot;system events&quot; to return (count of (every process whose bundle identifier is &quot;com.Growl.GrowlHelperApp&quot;)) &gt; 0'}
&nbsp;
if growl_running
  %x{osascript -e 'tell application id &quot;com.Growl.GrowlHelperApp&quot; to register as application &quot;Clip to Day One&quot; all notifications {&quot;Clip Complete&quot;} default notifications {&quot;Clip Complete&quot;} icon of application &quot;Day One&quot;'}
  %x{osascript -e 'tell application id &quot;com.Growl.GrowlHelperApp&quot; to notify with name &quot;Clip Complete&quot; title &quot;Log to Day One&quot; description &quot;Clipped to Day One&quot; application name &quot;Clip to Day One&quot;'}
end</pre></div></div>


<p><strong>Side note:</strong> I mentioned to <a href="https://twitter.com/#!/brianstucki">@brianstucki</a> that this Service might contain the necessary ingredients for an Evernote-to-Day-One solution, but I’ve realized it’s really only the last part of the equation. What you’d probably want to do with most RTF/text notes is export HTML, extract the “created on” meta and parse it into the correct date format, then pipe the rest of the contents through markdownify_cli.php, passing the result to <code>dayone new</code>. Then you’ll have nice, Markdown versions of your notes from Evernote, preserving much of the formatting. I tested this, and it works pretty flawlessly for text notes.</p>

<h3>Download</h3>

<p>For complete instructions on installing the service (and adding a keyboard shortcut for it), see the how-to <a href="http://brettterpstra.com/howtos/install-an-os-x-system-service/">posted here</a>.</p>

<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/ClipToDayOne.service.zip?9d7bd4" title="Download Clip to Day One Service (138)"><img src="http://cdn2.brettterpstra.com/wp-content/uploads/downloads/thumbnails/2012/01/dayoneautomator.jpg?9d7bd4" alt="download image for Clip to Day One Service" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/ClipToDayOne.service.zip?9d7bd4" title="Download Clip to Day One Service (138)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/ClipToDayOne.service.zip?9d7bd4" title="Download Clip to Day One Service (138)">Clip to Day One Service</a> — A System Service to clip any text to a Day One journal entry. <a href="http://brettterpstra.com/system-service-clip-to-day-one/">More Info</a></p></div>

<div class="footnotes">
<hr />
<ol>

<li id="fn:lb">
<p>If you missed it, you missed out, but it’s going to get even better. You’ll have a ton of opportunities in the next couple of months  to check out what is almost certainly–and it’s not just me saying this–the best tool available for live blogging events. <em>I’m so excited, I just can’t hide it…</em> <a href="#fnref:lb" rev="footnote">↩</a></p>
</li>

</ol>
</div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/quick-tip-quickly-clear-stuck-growl-notifications/' rel='bookmark' title='Quick Tip: Quickly clear stuck Growl notifications'>Quick Tip: Quickly clear stuck Growl notifications</a></li>
<li><a href='http://brettterpstra.com/a-system-service-for-to-url-shortening/' rel='bookmark' title='A System Service for to. url shortening'>A System Service for to. url shortening</a></li>
<li><a href='http://brettterpstra.com/updated-songza-lucky-link-service/' rel='bookmark' title='Updated: Songza Lucky Link Service'>Updated: Songza Lucky Link Service</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/system-service-clip-to-day-one/">System Service: Clip to Day One</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/system-service-clip-to-day-one/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Auto-convert your inline Markdown links to references</title>
		<link>http://brettterpstra.com/auto-convert-your-inline-markdown-links-to-references/</link>
		<comments>http://brettterpstra.com/auto-convert-your-inline-markdown-links-to-references/#comments</comments>
		<pubDate>Fri, 02 Sep 2011 19:14:55 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[markdownservices]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=2663</guid>
		<description><![CDATA[<p>Update: found a little bug (well, stupid mistake) in the HTML to Clipboard command. Download version is now 1.2.1, update if you grabbed 1.2. I’ve posted two more updates to the Markdown Service Tools. The first change is a fix for UTF-8 characters in the HTML to Clipboard Service I introduced yesterday. I had no idea that pbcopy didn’t like&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/auto-convert-your-inline-markdown-links-to-references/">Auto-convert your inline Markdown links to references</a></p>]]></description>
			<content:encoded><![CDATA[<p><strong>Update:</strong> found a little bug (well, stupid mistake) in the HTML to Clipboard command. Download version is now 1.2.1, update if you grabbed 1.2.</p>

<p>I’ve posted two more updates to the <a href="http://brettterpstra.com/project/markdown-service-tools/">Markdown Service Tools</a>. The first change is a fix for UTF-8 characters in the <strong>HTML to Clipboard</strong> Service I introduced yesterday. I had no idea that <code>pbcopy</code> didn’t like UTF-8 by default. I found <a href="http://hints.macworld.com/article.php?story=20081231012753422">a solution at Mac OS X Hints</a> which seems to be working. I updated the Service in the main download, let me know if it still has trouble with any UTF-8/16 characters.</p>

<p>Secondly, I added a Service that allows you to select an entire document’s text and convert any inline links to reference-style links, with the references sorted and neatly placed at the end of the document. It’s pretty smart about maintaining existing reference links, creating titles, recognizing multiple instances of links, etc., but I can’t account for everyone’s writing style. If you have a reasonable suggestion for improvements (or find any bugs, which is likely), do drop me a line and let me know.</p>

<p>Visit the <a href="http://brettterpstra.com/project/markdown-service-tools/">Markdown Service Tools project page</a> for full info and download.</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/a-service-for-writing-multimarkdown-footnotes-inline/' rel='bookmark' title='A Service for writing MultiMarkdown footnotes inline'>A Service for writing MultiMarkdown footnotes inline</a></li>
<li><a href='http://brettterpstra.com/some-chrome-love-for-the-markdown-service-tools/' rel='bookmark' title='Some Chrome love for the Markdown Service Tools'>Some Chrome love for the Markdown Service Tools</a></li>
<li><a href='http://brettterpstra.com/auto-link-text-service-updated/' rel='bookmark' title='Auto-link text service updated'>Auto-link text service updated</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/auto-convert-your-inline-markdown-links-to-references/">Auto-convert your inline Markdown links to references</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/auto-convert-your-inline-markdown-links-to-references/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>An average morning</title>
		<link>http://brettterpstra.com/an-average-morning/</link>
		<comments>http://brettterpstra.com/an-average-morning/#comments</comments>
		<pubDate>Fri, 02 Sep 2011 17:00:34 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[experiments]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[textmate]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=2622</guid>
		<description><![CDATA[<p>I was looking at some numbers on a web page. A wide variety of fairly large numbers. The web page didn’t provide any kind of average for the numbers, and I was curious. Curious, of course, meant writing a script to solve the problem. Yes, I could have copied the numbers out, punched them into a calculator one by one,&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/an-average-morning/">An average morning</a></p>]]></description>
			<content:encoded><![CDATA[<p>I was looking at some numbers on a web page. A wide variety of fairly large numbers. The web page didn’t provide any kind of average for the numbers, and I was curious. Curious, of course, meant writing a script to solve the problem. Yes, I could have copied the numbers out, punched them into a calculator one by one, or opened up Numbers and pasted them into cells… bah. I wanted to be able to copy text with all kinds of other junk in it and just get the average of all the values in contained quickly and easily (even if that meant wasting twice as much time up front).</p>

<p>I wrote the basic script in Ruby to run as a TextMate command:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby">input = STDIN.<span class="me1">read</span>
&nbsp;
<span class="co1"># Quick function to add commas to long values</span>
<span class="kw1">def</span> add_commas<span class="br0">&#40;</span> number <span class="br0">&#41;</span>
  number.<span class="me1">to_s</span>.<span class="me1">reverse</span>.<span class="me1">scan</span><span class="br0">&#40;</span><span class="sy0">/</span><span class="br0">&#40;</span>?:\d<span class="sy0">*</span>\.<span class="br0">&#41;</span>?\d<span class="br0">&#123;</span><span class="nu0">1</span>,<span class="nu0">3</span><span class="br0">&#125;</span><span class="sy0">-</span>?<span class="sy0">/</span><span class="br0">&#41;</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="st0">','</span><span class="br0">&#41;</span>.<span class="me1">reverse</span>
<span class="kw1">end</span>
&nbsp;
<span class="co1"># Scan for numbers in the text</span>
arr = input.<span class="me1">scan</span><span class="br0">&#40;</span><span class="sy0">/</span>\.?\d<span class="br0">&#91;</span>\d,<span class="br0">&#93;</span><span class="sy0">+</span><span class="br0">&#40;</span>?:\.\d<span class="sy0">+</span><span class="br0">&#41;</span>?<span class="sy0">/</span><span class="br0">&#41;</span>.<span class="me1">map</span><span class="br0">&#123;</span><span class="sy0">|</span>line<span class="sy0">|</span>
  <span class="co1"># remove non-decimal characters from results and convert to float</span>
  line.<span class="kw3">gsub</span><span class="br0">&#40;</span><span class="sy0">/</span><span class="br0">&#91;</span>^\d\.<span class="br0">&#93;</span><span class="sy0">/</span>,<span class="st0">''</span><span class="br0">&#41;</span>.<span class="me1">to_f</span>
<span class="br0">&#125;</span>.<span class="me1">sort</span>
&nbsp;
<span class="kw3">print</span> input <span class="co1"># output the original text</span>
&nbsp;
<span class="co1"># if there were 2 or more numbers found, output the additional information</span>
<span class="kw3">print</span> <span class="st0">&quot;<span class="es0">\n</span> - Average of #{arr.size} numbers ranging from #{arr[0]} to #{arr[arr.size-1]}: &quot;</span> <span class="sy0">+</span> add_commas<span class="br0">&#40;</span>arr.<span class="me1">inject</span><span class="br0">&#40;</span><span class="nu0">0.0</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="sy0">|</span>sum,el<span class="sy0">|</span> sum <span class="sy0">+</span> el <span class="br0">&#125;</span> <span class="sy0">/</span> arr.<span class="me1">size</span> <span class="br0">&#41;</span> <span class="kw1">unless</span> arr.<span class="me1">empty</span>? <span class="sy0">||</span> arr.<span class="me1">size</span> == <span class="nu0">1</span></pre></div></div>


<p>The script is simple enough that it should be easily adjustable to perform any kind of basic math on the array of numbers found in the text. The numbers don’t have to be in any order in the input; they can be listed vertically or horizontally or can just be scattered throughout text or messy table code. The regular expression should find them.</p>

<p>The TextMate command suited my needs just fine, but then I started thinking about sharing it. What format would make the most sense? A System Service that accepted text and appended a line with the average? A TextExpander snippet that ran on the clipboard? A LaunchBar action that worked with Instant Send or Copy/Paste? I couldn’t decide, and since the script was the only time-consuming part, I went ahead and made all of the above.</p>

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

<p>The TextExpander snippet is now in the Tools group of my TextExpander projects. If you’re subscribed to that group via URL, your group already updated with the “Average numbers in clipboard” snippet. Otherwise, go ahead and <a href="http://brettterpstra.com/share/te-snippets/index.php?group=Tools&amp;prefix=,,">download it or set up a new subscription</a>.</p>

<p>The other two versions (and the script) are in the download below, and I threw in the original TextMate command, too. The LaunchBar action is actually a Script Bundle with the Ruby script packaged inside. If you’ve ever wondered how to reference a self-contained script in AppleScript, it’s a decent example. It installs to <code>~/Library/Application Support/LaunchBar/Actions</code>. The System Service is a standard Automator action using the script above, and installs to <code>~/Library/Services</code>.</p>

<p>Want to see a video of it? Really? Why? I’m in that semi-asleep state where I thought it would be easier to show what it does than explain it. Since I doubt anyone else really has a need for this script, the video is a tribute to my ability to waste time in the early morning.</p>


  <!-- Begin Video.js -->
  <video class="video-js vjs-default-skin" width="600" height="338" poster="/share/video/average/averagePoster.jpg" controls 0 data-setup="{}">
    <source src="/share/video/average/average.mp4" type='video/mp4' />
    <source src="/share/video/average/average.webm" type='video/webm; codecs="vp8, vorbis"' />
    <source src="/share/video/average/average.ogv" type='video/ogg; codecs="theora, vorbis"' />
  </video>
  <!-- End Video.js -->


<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/AverageNumbers.zip?9d7bd4" title="Download Average Numbers in Selection (44)"><img src="http://cdn2.brettterpstra.com/wp-content/uploads/downloads/thumbnails/2011/09/AverageIcon.png?9d7bd4" alt="download image for Average Numbers in Selection" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/AverageNumbers.zip?9d7bd4" title="Download Average Numbers in Selection (44)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/AverageNumbers.zip?9d7bd4" title="Download Average Numbers in Selection (44)">Average Numbers in Selection</a> — A Ruby script, an OS X System Service and a LaunchBar action for finding any numbers in a block of text and returning the average. Also see the <a href="http://brettterpstra.com/share/te-snippets/index.php?group=Tools">Tools group</a> of the TextExpander Tools for a snippet version. <a href="http://brettterpstra.com/an-average-morning/">More Info</a></p></div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/geeklet-1-minute-average-cpu-load/' rel='bookmark' title='Geeklet: 1-minute average CPU load'>Geeklet: 1-minute average CPU load</a></li>
<li><a href='http://brettterpstra.com/seriously-easy-html5-video-encoding/' rel='bookmark' title='Seriously easy HTML5 video encoding'>Seriously easy HTML5 video encoding</a></li>
<li><a href='http://brettterpstra.com/fog-in-the-valley/' rel='bookmark' title='Fog In The Valley'>Fog In The Valley</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/an-average-morning/">An average morning</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/an-average-morning/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Some Chrome love for the Markdown Service Tools</title>
		<link>http://brettterpstra.com/some-chrome-love-for-the-markdown-service-tools/</link>
		<comments>http://brettterpstra.com/some-chrome-love-for-the-markdown-service-tools/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 21:23:21 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[System Service]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=2616</guid>
		<description><![CDATA[<p>The Markdown Service Tools–which already received one update today–just got a little bit of Chrome support. The “md — Links from Safari Tabs” now has a Chrome counterpart. At the time that I first wrote the Markdown Service Tools, Chrome didn’t support AppleScript well enough for this to be feasible, but opening up the AppleScript dictionary now reveals a full&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/some-chrome-love-for-the-markdown-service-tools/">Some Chrome love for the Markdown Service Tools</a></p>]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://brettterpstra.com/project/markdown-service-tools/">Markdown Service Tools</a>–which already received <a href="http://brettterpstra.com/new-markdown-service-tool-html-to-clipboard/">one update today</a>–just got a little bit of Chrome support. The “md — Links from Safari Tabs” now has a Chrome counterpart. At the time that I first wrote the Markdown Service Tools, Chrome didn’t support AppleScript well enough for this to be feasible, but opening up the AppleScript dictionary now reveals a full set of commands and objects. Nice to see.</p>

<p>I know there have been a lot of posts here today (at least compared to my average)… I’m on “vacation,” technically. I’m actually packing up boxes for a move to a new house over the next couple of days, and this is my OSHA break. I make no promises about keeping this rate of posting up!</p>

<p>Anyway, you can download the latest version of the Markdown Service Tools below, or <a href="http://brettterpstra.com/project/markdown-service-tools/">see the project page</a> for more information on all of the included services.</p>

<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/MarkdownServiceTools1.2.2.zip?9d7bd4" title="Download Markdown Service Tools (2952)"><img src="http://brettterpstra.com/wp-content/images/serviceicon.jpg?9d7bd4" alt="download image for Markdown Service Tools" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/MarkdownServiceTools1.2.2.zip?9d7bd4" title="Download Markdown Service Tools (2952)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/MarkdownServiceTools1.2.2.zip?9d7bd4" title="Download Markdown Service Tools (2952)">Markdown Service Tools</a> — Markdown Service Tools is a collection of OS X Services to make creating Markdown-formatted text that much easier. Services work in any Cocoa based application. <a href="http://brettterpstra.com/code/markdown-service-tools/">More Info</a></p></div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/new-markdown-service-tool-html-to-clipboard/' rel='bookmark' title='New Markdown Service tool: HTML to Clipboard'>New Markdown Service tool: HTML to Clipboard</a></li>
<li><a href='http://brettterpstra.com/auto-convert-your-inline-markdown-links-to-references/' rel='bookmark' title='Auto-convert your inline Markdown links to references'>Auto-convert your inline Markdown links to references</a></li>
<li><a href='http://brettterpstra.com/auto-link-text-service-updated/' rel='bookmark' title='Auto-link text service updated'>Auto-link text service updated</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/some-chrome-love-for-the-markdown-service-tools/">Some Chrome love for the Markdown Service Tools</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/some-chrome-love-for-the-markdown-service-tools/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Markdown Service tool: HTML to Clipboard</title>
		<link>http://brettterpstra.com/new-markdown-service-tool-html-to-clipboard/</link>
		<comments>http://brettterpstra.com/new-markdown-service-tool-html-to-clipboard/#comments</comments>
		<pubDate>Thu, 01 Sep 2011 14:43:18 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[multimarkdown]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=2600</guid>
		<description><![CDATA[<p>In response to a tweet from @gl3media, I’ve added a quick modification of the MultiMarkdown to HTML service to the Markdown Service Tools project page. It simply renders the selected text to HTML via MultiMarkdown 2 (Perl) and SmartyPants, putting the result on the clipboard and leaving the original text alone. I left it as the Perl version instead of&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/new-markdown-service-tool-html-to-clipboard/">New Markdown Service tool: HTML to Clipboard</a></p>]]></description>
			<content:encoded><![CDATA[<p>In response to a <a href="https://twitter.com/gl3media/status/109078575235334144">tweet from @gl3media</a>, I’ve added a quick modification of the MultiMarkdown to HTML service to the <a href="http://brettterpstra.com/project/markdown-service-tools/">Markdown Service Tools</a> project page. It simply renders the selected text to HTML via MultiMarkdown 2 (Perl) and SmartyPants, putting the result on the clipboard and leaving the original text alone.</p>

<p>I left it as the Perl version instead of the new PEG version because it was easier to embed, and allows me to force “snippet” rendering. Modify as you see fit, but this version makes a nice, neat package that does MultiMarkdown rendering without the need for any other installation. I thought others might find it useful, especially as an addition to Marked and nvALT capabilities, so here it is!</p>

<p>Download the service as part of the <a href="http://brettterpstra.com/project/markdown-service-tools/">Markdown Service Tools</a> package. See the how-to page on <a href="http://brettterpstra.com/howtos/install-an-os-x-system-service/">Installing System Services</a> if you have questions!</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/some-chrome-love-for-the-markdown-service-tools/' rel='bookmark' title='Some Chrome love for the Markdown Service Tools'>Some Chrome love for the Markdown Service Tools</a></li>
<li><a href='http://brettterpstra.com/quick-tip-clean-up-your-multimarkdown-tables/' rel='bookmark' title='Quick Tip: clean up your MultiMarkdown tables'>Quick Tip: clean up your MultiMarkdown tables</a></li>
<li><a href='http://brettterpstra.com/auto-convert-your-inline-markdown-links-to-references/' rel='bookmark' title='Auto-convert your inline Markdown links to references'>Auto-convert your inline Markdown links to references</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/new-markdown-service-tool-html-to-clipboard/">New Markdown Service tool: HTML to Clipboard</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/new-markdown-service-tool-html-to-clipboard/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>OS X Service for natural language dates</title>
		<link>http://brettterpstra.com/os-x-service-for-natural-language-dates/</link>
		<comments>http://brettterpstra.com/os-x-service-for-natural-language-dates/#comments</comments>
		<pubDate>Sat, 20 Aug 2011 15:00:09 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[automator]]></category>
		<category><![CDATA[date]]></category>
		<category><![CDATA[natural language]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=2539</guid>
		<description><![CDATA[<p>I knocked out a quick project before I got around to my first App Review, so I figured I’d go ahead and share it… A few people have requested a TextExpander set for dates. The problem is, getting the current date is easy with TextExpander variables, so that one’s not worth the time to me. Anything else requires some scripting,&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/os-x-service-for-natural-language-dates/">OS X Service for natural language dates</a></p>]]></description>
			<content:encoded><![CDATA[<p>I knocked out a quick project before I got around to my first App Review, so I figured I’d go ahead and share it…</p>

<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  src="http://cdn2.brettterpstra.com/wp-content/uploads/2011/08/calendarservice.jpg?9d7bd4" alt="calendar illustration" title="calendar illustration" width="197" height="332" class="shadow alignright size-full wp-image-2540" />A few people have requested a TextExpander set for dates. The problem is, getting the current date is easy with TextExpander variables, so that one’s not worth the time to me. Anything else requires some scripting, and to be really flexible the set would need to include a very large array of snippets; more than I could possibly keep straight. It could be done with one snippet if you could use the Fill In dialog as an input to a shell script, but you can’t (are you listening Smile?).</p>

<p>Instead, I whipped up a System Service this morning that lets you use keywords and natural language date input to return the specified date in various formats. You type out something like <code>date next tuesday</code>, select the text and run the Service and it will give you back <code>8/23/11</code>. If there’s no matching keyword at the beginning, it will assume <code>%c</code> (<a href="http://us3.php.net/manual/en/function.strftime.php">strftime formatting</a>) and give you back <code>Tue Aug 23 12:00:00 2011</code>.</p>

<p>The keywords are:</p>

<dl>
<dt><strong>date</strong> = ‘%m/%d/%y’ (slashed date)</dt>
<dd>“date today” gives you “8/20/11″</dd>

<dt><strong>local</strong> = ‘%F’ (localized date)</dt>
<dd>“local today” gives you (well, me) “2011–8-20″</dd>

<dt><strong>short</strong> = ‘%a, %b %d, %Y’ (abbreviated full date)</dt>
<dd>“short today” gives you “Sat, Aug 20, 2011″</dd>

<dt><strong>long</strong> = ‘%A, %B %d, %Y’ (long full date)</dt>
<dd>“long today” gives you “Saturday, August 20, 2011″</dd>
</dl>

<p>The language you can use depends on whether or not you have the “chronic” rubygem installed. If you can install rubygems, go to Terminal and run <code>sudo gem install chronic</code>. If that fails, no worries, it will use PHP’s <code>strtotime</code> to parse your string. It has a slightly more limited vocabulary, but anything like “wednesday,” “yesterday” or “next friday” will work.</p>

<p>It installs like any other service, and you can set a keyboard shortcut for it in <strong>System Preferences -&gt; Keyboard -&gt; Keyboard Shortcuts -&gt; Services</strong>. Refer to my <a href="http://brettterpstra.com/howtos/install-an-os-x-system-service/">how-to on Installing System Services</a> for a step-by-step explanation. This service was written on Lion, but should work fine on Snow Leopard, too.</p>

<p>Feel free to extend the script with more keywords and formats. It’s not too technical, just open up the workflow in Automator and find the case block for the keywords (around line 52). Then, copy the <code>when 'long' then '%A, %B %d, %Y'</code> format and paste new lines (or edit existing ones) before the <code>end</code> statement, keyword first then format (again, <a href="http://us3.php.net/manual/en/function.strftime.php">see PHP’s documentation</a> for strftime). Both Chronic and <code>strtotime</code> accept times as well, so if you wanted to do something like <code>date friday 3pm</code>, you could add the format string for a time specification to an existing or new keyword.</p>

<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/ConvertDateService.zip?9d7bd4" title="Download Convert Date - Natural Language Date Service (116)"><img src="http://brettterpstra.com/wp-content/images/serviceicon.jpg?9d7bd4" alt="download image for Convert Date - Natural Language Date Service" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/ConvertDateService.zip?9d7bd4" title="Download Convert Date - Natural Language Date Service (116)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/ConvertDateService.zip?9d7bd4" title="Download Convert Date - Natural Language Date Service (116)">Convert Date — Natural Language Date Service</a> — A System Service which takes selected text and parses it into a standard date format, using keywords at the beginning to define which format to use. <a href="http://brettterpstra.com/?p=2539">More Info</a></p></div>

<p><strong>Update:</strong> If you’re looking for something similar in Python, Macdrifter has <a href="http://www.macdrifter.com/2011/08/natural-language-date-replacements/">posted an alternative version</a> which works with Keyboard Maestro. Check it out.</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/natural-language-dates-for-textexpander/' rel='bookmark' title='Natural language dates for TextExpander'>Natural language dates for TextExpander</a></li>
<li><a href='http://brettterpstra.com/natural-language-date-conversion-for-textmate/' rel='bookmark' title='Natural language date conversion for TextMate'>Natural language date conversion for TextMate</a></li>
<li><a href='http://brettterpstra.com/updated-songza-lucky-link-service/' rel='bookmark' title='Updated: Songza Lucky Link Service'>Updated: Songza Lucky Link Service</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/os-x-service-for-natural-language-dates/">OS X Service for natural language dates</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/os-x-service-for-natural-language-dates/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Prefixr OS X Service</title>
		<link>http://brettterpstra.com/prefixr-service/</link>
		<comments>http://brettterpstra.com/prefixr-service/#comments</comments>
		<pubDate>Wed, 10 Aug 2011 03:21:27 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=2483</guid>
		<description><![CDATA[<p>Just for giggles, and because Jeffrey Way was kind enough to provide a simple API for Prefixr, here’s a System Service that will turn your standard CSS3 properties into cross-browser, vendor-prefixed versions. You can select an entire stylesheet and it will send back the text with the necessary changes, or just run it on a single rule to have it&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/prefixr-service/">Prefixr OS X Service</a></p>]]></description>
			<content:encoded><![CDATA[<p>Just for giggles, and because Jeffrey Way was kind enough to provide a simple API for <a href="http://prefixr.com/index.php">Prefixr</a>, here’s a System Service that will turn your standard CSS3 properties into cross-browser, vendor-prefixed versions.</p>

<p>You can select an entire stylesheet and it will send back the text with the necessary changes, or just run it on a single rule to have it vendor-prefixed for you. It turns this:</p>


<div class="wp_syntax"><div class="code"><pre class="css">p <span class="br0">&#123;</span>
  transition<span class="sy0">:</span> all .2s ease-in-out<span class="sy0">;</span>
  box-shadow<span class="sy0">:</span> <span class="re3">1px</span> <span class="re3">1px</span> <span class="re3">4px</span> rgba<span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">,</span><span class="nu0">0</span><span class="sy0">,</span><span class="nu0">0</span><span class="sy0">,</span>.3<span class="br0">&#41;</span> <span class="sy0">;</span>
  <span class="kw1">color</span><span class="sy0">:</span> <span class="re0">#333</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>


<p>into:</p>


<div class="wp_syntax"><div class="code"><pre class="css">p <span class="br0">&#123;</span>
	-webkit-transition<span class="sy0">:</span> all .2s ease-in-out<span class="sy0">;</span>
	-moz-transition<span class="sy0">:</span> all .2s ease-in-out<span class="sy0">;</span>
	-o-transition<span class="sy0">:</span> all .2s ease-in-out<span class="sy0">;</span>
	-ms-transition<span class="sy0">:</span> all .2s ease-in-out<span class="sy0">;</span>
	transition<span class="sy0">:</span> all .2s ease-in-out<span class="sy0">;</span>
&nbsp;
	-webkit-box-shadow<span class="sy0">:</span> <span class="re3">1px</span> <span class="re3">1px</span> <span class="re3">4px</span> rgba<span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">,</span><span class="nu0">0</span><span class="sy0">,</span><span class="nu0">0</span><span class="sy0">,</span>.3<span class="br0">&#41;</span><span class="sy0">;</span>
	-moz-box-shadow<span class="sy0">:</span> <span class="re3">1px</span> <span class="re3">1px</span> <span class="re3">4px</span> rgba<span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">,</span><span class="nu0">0</span><span class="sy0">,</span><span class="nu0">0</span><span class="sy0">,</span>.3<span class="br0">&#41;</span><span class="sy0">;</span>
	box-shadow<span class="sy0">:</span> <span class="re3">1px</span> <span class="re3">1px</span> <span class="re3">4px</span> rgba<span class="br0">&#40;</span><span class="nu0">0</span><span class="sy0">,</span><span class="nu0">0</span><span class="sy0">,</span><span class="nu0">0</span><span class="sy0">,</span>.3<span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
	<span class="kw1">color</span><span class="sy0">:</span> <span class="re0">#333</span><span class="sy0">;</span>
<span class="br0">&#125;</span></pre></div></div>


<p>Pretty handy. <a href="http://sass-lang.com/">Sass</a> can do this for you, and there are already plugins for TextMate, Vim, Espresso, Coda and more on Prefixr’s <a href="http://www.prefixr.com/api/usage/">API page</a>. Just thought I’d add one more to the pile.</p>

<p>Unzip it and drop it into <code>~/Library/Services</code>. Select some text containing CSS3 properties and right click on the selection, then look under “Services” for the Prefixer service. Run it and (assuming you have an internet connection), it’ll do some of the tedious parts of CSS3 for you.</p>

<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/PrefixrService.zip?9d7bd4" title="Download Prefixr Service (245)"><img src="http://brettterpstra.com/wp-content/images/serviceicon.jpg?9d7bd4" alt="download image for Prefixr Service" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/PrefixrService.zip?9d7bd4" title="Download Prefixr Service (245)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/PrefixrService.zip?9d7bd4" title="Download Prefixr Service (245)">Prefixr Service</a> — Uses the Prefixr.com API to process your standard CSS3 properties into cross-browser, vendor-prefixed versions. <a href="">More Info</a></p></div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/app-review-gradient/' rel='bookmark' title='App Review: Gradient'>App Review: Gradient</a></li>
<li><a href='http://brettterpstra.com/a-little-hootsuite-userstyling/' rel='bookmark' title='A little HootSuite userstyling'>A little HootSuite userstyling</a></li>
<li><a href='http://brettterpstra.com/fixing-gleebox/' rel='bookmark' title='Fixing Gleebox'>Fixing Gleebox</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/prefixr-service/">Prefixr OS X Service</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/prefixr-service/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Quick Tip: clean up your MultiMarkdown tables</title>
		<link>http://brettterpstra.com/quick-tip-clean-up-your-multimarkdown-tables/</link>
		<comments>http://brettterpstra.com/quick-tip-clean-up-your-multimarkdown-tables/#comments</comments>
		<pubDate>Tue, 24 May 2011 02:52:25 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[automator]]></category>
		<category><![CDATA[multimarkdown]]></category>
		<category><![CDATA[quicktip]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[service]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/quick-tip-clean-up-your-multimarkdown-tables/</guid>
		<description><![CDATA[<p>Quick tips are random posts regarding something I discovered on my way to something bigger. They usually get longer than “quick” would imply, for which I refuse to apologize. The table syntax in MultiMarkdown is intuitive and can be really fast to work with. Much faster than coding HTML tables, to be sure. Unless you’re pretty religious about your spacing,&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/quick-tip-clean-up-your-multimarkdown-tables/">Quick Tip: clean up your MultiMarkdown tables</a></p>]]></description>
			<content:encoded><![CDATA[<p><em><a href="http://brettterpstra.com/tag/quicktip/">Quick tips</a> are random posts regarding something I discovered on my way to something bigger. They usually get longer than “quick” would imply, for which I refuse to apologize.</em></p>

<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  src="http://cdn2.brettterpstra.com/wp-content/uploads/2011/05/table_demo_after.jpg?9d7bd4" class="alignright shadow"/>The table syntax in MultiMarkdown is intuitive and can be really fast to work with. Much faster than coding HTML tables, to be sure. Unless you’re pretty religious about your spacing, though, the plain text version can get out of hand pretty quickly. If only there were some way to make them pretty in one click…</p>

<p>You’ve already got the tools, I would imagine, but you might not have known they were there. I didn’t notice until tonight, but I don’t work with tables much in MultiMarkdown. In the “Utilities” folder of the MultiMarkdown installation there’s a Perl script that will do amazing things to messy MultiMarkdown tables. The more I play with it, the more I think that <a href="http://fletcherpenney.net/">Fletcher Penney</a> is a genius.</p>

<p>My advice? Make it into a System Service and use it everywhere. Just open up the file at <code>~/Library/Application Support/MultiMarkdown/Utilities/table_cleanup.pl</code> in your favorite text editor. Open Automator and create a new Service, dragging the Run Shell Script action into the right panel. Set it to Perl, accept text, replace text and copy the contents of the script into the action. Save it and run it on some table text! If you’re running any of the <a href="http://brettterpstra.com/project/markdown-service-tools/">Markdown Service Tools</a>, you can name it “md — Clean Up Tables” and it will fit right in with your Services menu.</p>

<p>Play around with it, it’s pretty amazing. You can control certain aspects of the results by messing with the header rows, and it even centers text in centered columns (<code>:----:</code>). Thank you, Fletcher Penney.</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/a-few-themes-for-multimarkdown-composer/' rel='bookmark' title='A few themes for MultiMarkdown Composer'>A few themes for MultiMarkdown Composer</a></li>
<li><a href='http://brettterpstra.com/taking-the-markdown-to-evernote-service-further/' rel='bookmark' title='Taking the Markdown to Evernote service further'>Taking the Markdown to Evernote service further</a></li>
<li><a href='http://brettterpstra.com/new-markdown-service-tool-html-to-clipboard/' rel='bookmark' title='New Markdown Service tool: HTML to Clipboard'>New Markdown Service tool: HTML to Clipboard</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/quick-tip-clean-up-your-multimarkdown-tables/">Quick Tip: clean up your MultiMarkdown tables</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/quick-tip-clean-up-your-multimarkdown-tables/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Watch for file changes and refresh your browser automatically</title>
		<link>http://brettterpstra.com/watch-for-file-changes-and-refresh-your-browser-automatically/</link>
		<comments>http://brettterpstra.com/watch-for-file-changes-and-refresh-your-browser-automatically/#comments</comments>
		<pubDate>Mon, 07 Mar 2011 08:33:34 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[automator]]></category>
		<category><![CDATA[os x]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[webdev]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=2056</guid>
		<description><![CDATA[<p>After my epic three-part post on Saturday, I spent the rest of the weekend doing more “useful” things. Now it’s Sunday night (Monday morning, I think), and I’ve got some kind of minor food poisoning which is currently keeping me awake. Thus a “hey, cool trick” post. I actually already own an app which can do this to some extent,&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/watch-for-file-changes-and-refresh-your-browser-automatically/">Watch for file changes and refresh your browser automatically</a></p>]]></description>
			<content:encoded><![CDATA[<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  src="http://cdn2.brettterpstra.com/wp-content/uploads/2011/03/magcodepic.jpg?9d7bd4" alt="Post image for Watcher Service" title="Code Watcher" width="288" height="263" class="alignright size-full wp-image-2062" />After my epic three-part post on Saturday, I spent the rest of the weekend doing more “useful” things. Now it’s Sunday night (Monday morning, I think), and I’ve got some kind of minor food poisoning which is currently keeping me awake. Thus a “hey, cool trick” post.</p>

<p>I actually already own an app which can do this to some extent, and I know there are more available. I like to do things the hard way once in a while. What I wanted was a basic script which could execute arbitrary code whenever a file of a certain type changed within a directory. The use case is web development: whenever I change a site-related file (html, php, css, less, rb, erb, etc.), I want Safari to refresh the related page.</p>

<p>Folder Actions don’t work well on my system (do they work for anyone?). Hazel would work, but I needed something more immediate. I had a version that used <code>launchd</code>, but it was difficult to consistently start and stop from a script. Here’s the final solution I came up with.</p>

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

<p>At the top, let me say that the heavy lifting in my script was taken from a SASS file-watching script by <a href="https://github.com/carlo/haml-sass-file-watcher">Carlo Zottman</a>. It uses Ruby to poll a file collection for modification date variations, and keeps a pretty low profile. I wanted to avoid compiled code for this, as I eventually do want to go to bed tonight.</p>

<p>The basic goals:</p>

<ul>
<li>Watch only files of a specific type</li>
<li>Refresh my primary browser when a change occurs</li>
<li>Refresh across windows and tabs, but limit by user-specified keyword in URL</li>
</ul>

<p>I built both a command line script and a System Service to do this, and both work as standalone solutions. The Automator action makes it possible to right click a folder in Finder and choose “Watcher” to start watching it, and it asks you for the tab keyword in a nice popup dialog. Beyond that, it really just wraps the command line script. You can modify either with the following instructions.</p>

<p>Here’s the command line version:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby"><span class="co1">#!/usr/bin/env ruby</span>
<span class="co1"># watch.rb by Brett Terpstra, 2011 &lt;http://brettterpstra.com&gt;</span>
<span class="co1"># with credit to Carlo Zottmann &lt;https://github.com/carlo/haml-sass-file-watcher&gt;</span>
&nbsp;
<span class="kw3">trap</span><span class="br0">&#40;</span><span class="st0">&quot;SIGINT&quot;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="kw3">exit</span> <span class="br0">&#125;</span>
&nbsp;
<span class="kw1">if</span> ARGV.<span class="me1">length</span> <span class="sy0">&lt;</span> <span class="nu0">2</span>
  <span class="kw3">puts</span> <span class="st0">&quot;Usage: #{$0} watch_folder keyword&quot;</span>
  <span class="kw3">puts</span> <span class="st0">&quot;Example: #{$0} . mywebproject&quot;</span>
  <span class="kw3">exit</span>
<span class="kw1">end</span>
&nbsp;
dev_extension = <span class="st0">'dev'</span>
filetypes = <span class="br0">&#91;</span><span class="st0">'css'</span>,<span class="st0">'html'</span>,<span class="st0">'htm'</span>,<span class="st0">'php'</span>,<span class="st0">'rb'</span>,<span class="st0">'erb'</span>,<span class="st0">'less'</span>,<span class="st0">'js'</span><span class="br0">&#93;</span>
watch_folder = ARGV<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>
keyword = ARGV<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>
<span class="kw3">puts</span> <span class="st0">&quot;Watching #{watch_folder} and subfolders for changes in project files...&quot;</span>
&nbsp;
<span class="kw1">while</span> <span class="kw2">true</span> <span class="kw1">do</span>
  files = <span class="br0">&#91;</span><span class="br0">&#93;</span>
  filetypes.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>type<span class="sy0">|</span>
    files <span class="sy0">+</span>= <span class="kw4">Dir</span>.<span class="me1">glob</span><span class="br0">&#40;</span> <span class="kw4">File</span>.<span class="me1">join</span><span class="br0">&#40;</span> watch_folder, <span class="st0">&quot;**&quot;</span>, <span class="st0">&quot;*.#{type}&quot;</span> <span class="br0">&#41;</span> <span class="br0">&#41;</span>
  <span class="br0">&#125;</span>
  new_hash = files.<span class="me1">collect</span> <span class="br0">&#123;</span><span class="sy0">|</span>f<span class="sy0">|</span> <span class="br0">&#91;</span> f, <span class="kw4">File</span>.<span class="me1">stat</span><span class="br0">&#40;</span>f<span class="br0">&#41;</span>.<span class="me1">mtime</span>.<span class="me1">to_i</span> <span class="br0">&#93;</span> <span class="br0">&#125;</span>
  hash <span class="sy0">||</span>= new_hash
  diff_hash = new_hash <span class="sy0">-</span> hash
&nbsp;
  <span class="kw1">unless</span> diff_hash.<span class="me1">empty</span>?
    hash = new_hash
&nbsp;
    diff_hash.<span class="me1">each</span> <span class="kw1">do</span> <span class="sy0">|</span>df<span class="sy0">|</span>
      <span class="kw3">puts</span> <span class="st0">&quot;Detected change in #{df[0]}, refreshing&quot;</span>
      <span class="sy0">%</span>x<span class="br0">&#123;</span>osascript<span class="co4">&lt;&lt;ENDGAME
        	tell application &quot;Safari&quot;
          	set windowList to every window
          	repeat with aWindow in windowList
          		set tabList to every tab of aWindow
          		repeat with atab in tabList
          			if (URL of atab contains &quot;#{keyword}&quot;) then
          			  tell atab to do javascript &quot;window.location.reload()&quot;
          			end if
          		end repeat
          	end repeat
        	end tell
ENDGAME</span>
<span class="br0">&#125;</span>
    <span class="kw1">end</span>
  <span class="kw1">end</span>
&nbsp;
  <span class="kw3">sleep</span> <span class="nu0">1</span>
<span class="kw1">end</span></pre></div></div>


<h2>Installing</h2>

<p>If you want to use the above script from Terminal, just put it in a directory in your path and run <code>chmod a+x watch.rb</code> on it. Then you can call it with <code>watch.rb folder/to/watch keyword</code>. The keyword you pass will determine which tabs will refresh in your browser. For example, if I’m working on dev.heckyesmarkdown.com (my local development version), I would use “dev.heckyes” to limit the refresh to only associated tabs. Once the script is running, you can stop it any time by typing Control-C in that Terminal. If you’ve run it in the background, you’ll either need to foreground it or kill it manually.</p>

<p>To install the System Service, <a href="#download">download the workflow</a>, unzip it and place it in <code>~/Library/Services</code> (where ‘~’ is your home folder). It will now show up when you right click on one or more selected folders in the Finder. Choose “Watcher,” enter a URL-matching keyword and let it go. You should see the spinning gear icon in your menubar. When you want to stop watching the folder, click that icon and choose “Stop Watcher”.</p>

<h2>Customizing</h2>

<p>In the standalone Ruby script (above), you can easily modify the watched filetypes in line 14, and you can replace the AppleScript with your own starting on line 34. I’ll offer some examples for other browsers below.</p>

<p>The Service contains pretty much the same script, but modified to work with an Automator workflow. If you open it in Automator and skip to the last action, you’ll see the script and you can make your filetype and AppleScript modifications in there.</p>

<h3>Using other browsers</h3>

<p>Chrome has decent AppleScript support these days, so changing this script to work with it is trivial. Just replace the AppleScript portion (beginning with “tell application…”) with the following:</p>


<div class="wp_syntax"><div class="code"><pre class="applescript"><span class="kw3">tell</span> <span class="kw1">application</span> <span class="st0">&quot;Google Chrome&quot;</span>
	<span class="kw3">set</span> windowList <span class="kw3">to</span> <span class="kw2">every</span> <span class="kw1">window</span>
	<span class="kw3">repeat</span> <span class="kw3">with</span> aWindow <span class="kw3">in</span> windowList
		<span class="kw3">set</span> tabList <span class="kw3">to</span> <span class="kw2">every</span> <span class="kw1">tab</span> <span class="kw3">of</span> aWindow
		<span class="kw3">repeat</span> <span class="kw3">with</span> atab <span class="kw3">in</span> tabList
			<span class="kw3">if</span> <span class="br0">&#40;</span>URL <span class="kw3">of</span> atab <span class="kw2">contains</span> <span class="st0">&quot;#{keyword}&quot;</span><span class="br0">&#41;</span> <span class="kw3">then</span>
				<span class="kw3">tell</span> atab <span class="kw3">to</span> reload
			<span class="kw3">end</span> <span class="kw3">if</span>
		<span class="kw3">end</span> <span class="kw3">repeat</span>
	<span class="kw3">end</span> <span class="kw3">repeat</span>
<span class="kw3">end</span> <span class="kw3">tell</span></pre></div></div>


<p>Firefox is a little less elegant, as far as I know, and requires System Events scripting to refresh a page. If you know a better way, I’d love to hear it, but here’s a basic script for reloading the front page. You might as well delete the keyword portions of the script/workflow if you go this route, they won’t be applicable:</p>


<div class="wp_syntax"><div class="code"><pre class="applescript"> <span class="kw3">tell</span> app <span class="st0">&quot;Firefox&quot;</span> <span class="kw3">to</span> <span class="kw1">activate</span>
 <span class="kw3">tell</span> app <span class="st0">&quot;System Events&quot;</span>
   keystroke <span class="st0">&quot;r&quot;</span> using command down
 <span class="kw3">end</span> <span class="kw3">tell</span></pre></div></div>


<p>I won’t detail any other browsers; if you’re doing web development in something more exotic, I’ll assume you know how to script it.</p>

<h3>Executing arbitrary code</h3>

<p>You don’t have to refresh browsers with this. You don’t even have to use it for web development. Have it watch text files for changes and run an iCal script when one is modified. It’s basically a hyperactive Folder Action.</p>

<p>If you want to have the script do something new every time you use it, you might want to externalize the action code. Just modify the <code>diff_hash.each do |df|</code> block to run an outside script. If it’s shell code, just make it executable and call it with <code>%x{path/to/script}</code>, and if it’s AppleScript, call it with <code>%x{/usr/bin/osascript path/to/script}</code>. Then you can modify the action script each time without changing the watch.rb file.</p>

<p>If you want to get really crazy, you could pass the script to execute as a command line parameter, or request it in the Automator workflow and pass it in. I don’t have a need for that right now, but if you build it, let me know!</p>

<p>I hope folks find this useful. Now, excuse me while I go retch for a little bit.</p>

<h2 id="download">Download</h2>

<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/Watcher.zip?9d7bd4" title="Download Watcher Service (172)"><img src="http://brettterpstra.com/wp-content/images/serviceicon.jpg?9d7bd4" alt="download image for Watcher Service" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/Watcher.zip?9d7bd4" title="Download Watcher Service (172)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/Watcher.zip?9d7bd4" title="Download Watcher Service (172)">Watcher Service</a> — A Snow Leopard System Service that runs on folders in Finder. By default, it watches for changes to web dev files and refreshes Safari, but it can be customized extensively. See the “more info” link for customization instructions. <a href="http://brettterpstra.com/?p=2056">More Info</a></p></div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/os-x-service-for-natural-language-dates/' rel='bookmark' title='OS X Service for natural language dates'>OS X Service for natural language dates</a></li>
<li><a href='http://brettterpstra.com/a-few-scripts-for-taskpaper-users/' rel='bookmark' title='A few scripts for TaskPaper users'>A few scripts for TaskPaper users</a></li>
<li><a href='http://brettterpstra.com/a-bash-function-for-markdown-bloggers/' rel='bookmark' title='A Bash function for Markdown bloggers'>A Bash function for Markdown bloggers</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/watch-for-file-changes-and-refresh-your-browser-automatically/">Watch for file changes and refresh your browser automatically</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/watch-for-file-changes-and-refresh-your-browser-automatically/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Automated search and link text Service</title>
		<link>http://brettterpstra.com/automated-search-and-link-text-service/</link>
		<comments>http://brettterpstra.com/automated-search-and-link-text-service/#comments</comments>
		<pubDate>Tue, 14 Sep 2010 23:52:15 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[experiments]]></category>
		<category><![CDATA[search]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[snow leopard]]></category>
		<category><![CDATA[yahoo]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=961</guid>
		<description><![CDATA[<p>Update: Download link has been updated with a new Bing version. The Yahoo search API was sunset recently and the original service fails to work now. The new download will work for the time being… I’ve had this one laying around for a long time, so I thought I’d toss it out on the ‘net and see if anyone else&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/automated-search-and-link-text-service/">Automated search and link text Service</a></p>]]></description>
			<content:encoded><![CDATA[<p><strong>Update:</strong> Download link has been updated with a new Bing version. The Yahoo search API was sunset recently and the original service fails to work now. The new download will work for the time being…</p>

<p>I’ve had this one laying around for a long time, so I thought I’d toss it out on the ‘net and see if anyone else had a use for it. It’s actually really handy, and a big timesaver. It takes selected text and uses the Yahoo API to run a quick search for that term, and returns the result as a Markdown link. You can, of course, modify the output to any text-based markup (Rich Text links are a pain).</p>

<p>There’s a quick video of it in action in the full post, plus some extra info and a download link…</p>

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

<p>The Service is called “First Yahoo Link,” and does exactly that. In the video below, I just wrote out some random words that were pretty sure to have predictable search results. The more vague the search terms, the more unpredictable the result, obviously. I’m running the Service with the shortcut <code>CTRL-SHIFT-Y</code>, which I set in the Keyboard pane of the System Preferences. Here goes:</p>

<p><video width="480" height="270" controls="" autobuffer="autobuffer">
    <source src="http://cdn.brettterpstra.com/media/newfirstyahoolink2.mp4" type='video/mp4; codecs="avc1.42E01E, mp4a.40.2"'>
    <source src="http://cdn.brettterpstra.com/media/newfirstyahoolink2.ogv"  type='video/ogg; codecs="theora, vorbis"'>
</video></p>

<p>The majority of the code is a Yahoo API wrapper for Ruby by <a href="http://premshree.livejournal.com/">Premshree Pillai</a>. I just shoved it into my Run Shell Script action in the Automator Workflow and built off of it. It just escapes your selected text, passes it to a Web search and then formats the first result in the returned array. There’s probably a lot more you could do with it, but I like its simplicity and relative speed. It’s definitely faster than flipping over to a browser, running a search and copying a link, coming back and pasting/formatting it manually.</p>

<p>Give it a shot, you never know, you just might like it.</p>

<p>Oh, and in case you haven’t been through this drill before, unzip the file, put the resulting <code>workflow</code> file in ~/Library/Services and then go into System Preferences &gt; Keyboard &gt; Keyboard Shortcuts and add a shortcut key for the “First Yahoo Link” service you should now have in there. Then just select text and hit your shortcut key (or pull it down in the Application &gt; Services menu). Done.</p>

<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/AutoLinkWebSearch.zip?9d7bd4" title="Download Auto-link Web Search (145)"><img src="http://brettterpstra.com/wp-content/images/serviceicon.jpg?9d7bd4" alt="download image for Auto-link Web Search" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/AutoLinkWebSearch.zip?9d7bd4" title="Download Auto-link Web Search (145)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/AutoLinkWebSearch.zip?9d7bd4" title="Download Auto-link Web Search (145)">Auto-link Web Search</a> — A Snow Leopard Service that takes selected text, runs a Bing search for it and returns the first result as a Markdown link around the original text. <a href="http://brettterpstra.com/automated-search-and-link-text-service/">More Info</a></p></div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/auto-link-text-service-updated/' rel='bookmark' title='Auto-link text service updated'>Auto-link text service updated</a></li>
<li><a href='http://brettterpstra.com/songza-lucky-link-service/' rel='bookmark' title='Songza Lucky Link Service'>Songza Lucky Link Service</a></li>
<li><a href='http://brettterpstra.com/updated-songza-lucky-link-service/' rel='bookmark' title='Updated: Songza Lucky Link Service'>Updated: Songza Lucky Link Service</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/automated-search-and-link-text-service/">Automated search and link text Service</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/automated-search-and-link-text-service/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
<enclosure url="http://cdn.brettterpstra.com/media/newfirstyahoolink2.ogv" length="853095" type="video/ogg" />
<enclosure url="http://cdn.brettterpstra.com/media/newfirstyahoolink2.mp4" length="2168040" type="video/mp4" />
		</item>
		<item>
		<title>Is your URL too short? Try our system, free!</title>
		<link>http://brettterpstra.com/is-your-url-too-short-try-our-system-free/</link>
		<comments>http://brettterpstra.com/is-your-url-too-short-try-our-system-free/#comments</comments>
		<pubDate>Sat, 14 Aug 2010 15:00:05 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[experiments]]></category>
		<category><![CDATA[launchbar]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[snow leopard]]></category>
		<category><![CDATA[terminal]]></category>
		<category><![CDATA[url shortener]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=899</guid>
		<description><![CDATA[<p>I was sifting through my previous blog after Jeffery Zeldman kindly sent a lot of visitors in that direction for some TextMate starter tips. Whilst milling around, I stumbled upon an old trick I used to use in Quicksilver (before I gave up on it1), but had forgotten about since. It’s a very simple little shell command which uses curl&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/is-your-url-too-short-try-our-system-free/">Is your URL too short? Try our system, free!</a></p>]]></description>
			<content:encoded><![CDATA[<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  src="http://cdn2.brettterpstra.com/wp-content/uploads/2010/08/urlextender_system.jpg?9d7bd4" alt="URL Extender System" border="0" width="300" height="260" class="alignright noshadow" />I was sifting through my <a href="http://blog.circlesixdesign.com">previous blog</a> after Jeffery Zeldman kindly <a href="http://www.zeldman.com/2010/08/13/how-to-use-textmate/">sent a lot of visitors</a> in that direction for some <a href="http://blog.circlesixdesign.com/2007/01/02/digging-in-to-textmate/">TextMate starter tips</a>. Whilst milling around, I stumbled upon an <a href="http://blog.circlesixdesign.com/2007/10/19/reverse-shortened-urls-with-quicksilver/">old trick I used to use</a> in <a href="http://www.blacktree.com/">Quicksilver</a> (before I gave up on it<sup id="fnref:quicksilver"><a href="#fn:quicksilver" rel="footnote">1</a></sup>), but had forgotten about since.</p>

<p>It’s a very simple little shell command which uses <code>curl</code> to track down the destination of a shortened url (or any link with a redirect). It works with an assortment of services, including bit.ly, tinyurl.com, ow.ly, etc. It returns the destination address (the original url), and you can pass that on to whatever you like!</p>

<p><strong>Side note</strong>: I’ve been working on a little site called <a href="http://justthelinks.com">JustTheLinks</a> which makes liberal use of url-lengthening. It grabs all of your tweets from your home timeline which contain links, and creates a live-updated list with expanded urls and titles. It uses PHP’s curl to do the trick, so it’s the same concept. It’s “in-progress,” but feel free to check it out at <a href="http://justthelinks.com">http://justthelinks.com</a>!</p>

<p>Anyway, I decided to update the Quicksilver action and adapt it for some other uses. I’m happy to report that it’s still quite useful as a command line script, a LaunchBar action or a System Service. This post has code for all three, so take your pick!</p>

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

<p>The <code>curl</code> command in this script has two options specified, –I and –s. –I tells it to fetch only the headers of the requested URI, and the –s tells it to suppress error messages (silent). The result is a short response which contains the location of the redirect, which is piped to <code>awk</code>. We look for the line in the response containing “Location” and print the second field of that line, which is the destination url. Here are a few ways I thought of to put it to use:</p>

<h3>Terminal</h3>

<p>The first thing I did was whip up a shell script to run from the command line. Just create a text file wherever you keep scripts<sup id="fnref:scripts"><a href="#fn:scripts" rel="footnote">2</a></sup>, or make a new directory somewhere for it. Paste in the code below, and name it something that makes sense to you. I went with <code>follow</code>, because it’s following the redirect path, and <code>expand</code> was taken (and lengthen didn’t seem as much fun to type…). The script looks for a single argument, which would be the shortened url, and if it doesn’t receive one it tries the clipboard. So, if you already have the url in your clipboard, which is a pretty safe bet in this case, you can just run the script with no arguments.</p>

<div markdown=0>
<pre><code class="bash">
#!/bin/bash

if [ $# -eq 0 ]; then
  curl -Is `pbpaste` | awk &#x27;/Location/ { print $2 }&#x27;  
else
  curl -Is $1 | awk &#x27;/Location/ { print $2 }&#x27;
fi
</code></pre>
</div>

<h3>LaunchBar</h3>

<p>I heart <a href="http://www.obdev.at/products/launchbar/index.html" title="LaunchBar 5">LaunchBar</a>. Like Quicksilver, you can easily build “actions” for it that act on different types of input. This one just acts on text you paste or send to it, and assumes it’s going to be a shortened URL. After it lengthens it, it just displays the result as large popup text. If you wanted to, you could easily have it <code>open location</code> or whatever, but the whole point is just to see where you’re going, right?</p>

<p>This just goes into <code>~/Library/Application Support/LaunchBar/Actions</code> as a compiled AppleScript (scpt) file. Open AppleScript Editor and paste in the code below (or just <a href="applescript://com.apple.scripteditor?action=new&amp;script=on%20handle_string%28message%29%0A%09%0A%09tell%20application%20%22LaunchBar%22%0A%09%09set%20_res%20to%20do%20shell%20script%20%22curl%20%2DIs%20%22%20%26%20message%20%26%20%22%20%7C%20awk%20%27%2FLocation%2F%20%7B%20print%20%242%20%7D%27%22%0A%09%09display%20in%20large%20type%20_res%0A%09end%20tell%0A%09%0Aend%20handle_string">click here to open it automatically</a> in your editor). Save the file to the Actions folder and give it a name you’ll recognize. Mine’s called ‘Expand Shortened URL.scpt’. Clever, I know. Here’s the code:</p>

<div markdown=0>
<pre><code class="as">
on handle_string(message)

    tell application &quot;LaunchBar&quot;
        set _res to do shell script &quot;curl -Is &quot; &amp; message &amp; &quot; | awk &#x27;/Location/ { print $2 }&#x27;&quot;
        display in large type _res
    end tell

end handle_string
</code></pre>
</div>

<h3>Snow Leopard Service</h3>

<p>Lastly, here’s a System Service that you can run on selected text in any Cocoa application. I’ve previously posted a <a href="http://brettterpstra.com/a-system-service-for-to-url-shortening/">Service for shortening urls</a>, so here’s the opposite. This one can actually take a whole block of text and will scan for any and all links in it, attempting to lengthen and replace any shortened urls in the text. Here’s how to build it:</p>

<ul>
<li>Open Automator.app</li>
<li>Select “Service” from the new file menu</li>
<li>Set “Service receives selected” to “text” in “any application”</li>
<li>Check the “Replaces selected text” box</li>
<li>Find the “Run Shell Script” action on the left and drag it into your workflow on the right</li>
<li>Set the Shell to Ruby (in this case)</li>
<li>Paste in the code below</li>
<li>Save the file to the <code>~/Library/Services</code> folder, named something like “Expand shortened urls in selection” (or something more interesting)</li>
</ul>

<p>Now, when you select text in any Cocoa application (Safari, Mail, TextEdit, etc.), you’ll be able to find your Service in the Services submenu of either the application menu in the menubar, or in the contextual menu that comes up when you right click (ctrl-click) the selected text. When you run it, it will replace your text with a new version with any shortened urls in it expanded.</p>

<div markdown=0>
<pre><code class="ruby">
#!/usr/bin/env ruby -rjcode -Ku

require &#x27;open-uri&#x27;

input = STDIN.read
links = input.scan(/\b((?:https?:\/\/)(?:www\.)?([^\/]+)\/[a-zA-Z0-9]+[^\s`!()\[\]{};:&#x27;&quot;.,&lt;&gt;?&laquo;&raquo;&ldquo;&rdquo;&lsquo;&rsquo;])/im)
links.each {|link|
  result = %x{curl -Is #{link[0]} | awk &#x27;/Location/ { print $2 }&#x27;}
  input = input.gsub(/#{link[0]}/,result.strip)
}
print input
</code></pre>
</div>

<p>How often will you need any of these little experiments? Probably not very often. Most of the time, I’m more than happy to just follow a shortened link and trust that the description it came with will hold true. Every once in a while, though, I come across a link of unknown origin that I’d prefer to run through something like this. Hopefully you’ll be able to find a use for it, too. It’s a cool little snippet.</p>

<div class="footnotes">
<hr />
<ol>

<li id="fn:quicksilver">
<p>Sorry, Quicksilver fans. It used to be my absolute, must-have, favorite thing in the world, but it got too crashy on Snow Leopard, and then development just kind of died. <a href="http://www.obdev.at/products/launchbar/index.html" title="LaunchBar 5">LaunchBar</a> is way better these days. <a href="#fnref:quicksilver" rev="footnote">↩</a></p>
</li>

<li id="fn:scripts">
<p>I keep a ‘scripts’ folder in my home directory (~/scripts) and put that in my PATH environment variable in my .bash_profile. Then, I can run my scripts from anywhere but don’t have to muck around in <code>/usr/local/bin</code> or any such thing. <a href="#fnref:scripts" rev="footnote">↩</a></p>
</li>

</ol>
</div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/a-system-service-for-to-url-shortening/' rel='bookmark' title='A System Service for to. url shortening'>A System Service for to. url shortening</a></li>
<li><a href='http://brettterpstra.com/launchbar-actions-for-url-encoding-and-decoding/' rel='bookmark' title='LaunchBar actions for url encoding and decoding'>LaunchBar actions for url encoding and decoding</a></li>
<li><a href='http://brettterpstra.com/a-better-os-x-system-service-for-evernote-notes-with-multimarkdown/' rel='bookmark' title='A better System Service for Evernote clipping — with MultiMarkdown'>A better System Service for Evernote clipping — with MultiMarkdown</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/is-your-url-too-short-try-our-system-free/">Is your URL too short? Try our system, free!</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/is-your-url-too-short-try-our-system-free/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EverSave revisited, now with session restore!</title>
		<link>http://brettterpstra.com/eversave-revisited-now-with-session-restore/</link>
		<comments>http://brettterpstra.com/eversave-revisited-now-with-session-restore/#comments</comments>
		<pubDate>Fri, 16 Jul 2010 01:50:46 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[applescript]]></category>
		<category><![CDATA[evernote]]></category>
		<category><![CDATA[safari]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[snow leopard]]></category>
		<category><![CDATA[System Service]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=744</guid>
		<description><![CDATA[<p>Safari 5 has brought several solutions for managing lists of open tabs, from the simple (like my TabLinks extension) to full session-management capabilities (see the beautiful Sessions extension). However, I’ve found I still like using my EverSave script in many situations, primarily because it allows me to annotate, tag and sync my important sessions for later retrieval. One thing’s been&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/eversave-revisited-now-with-session-restore/">EverSave revisited, now with session restore!</a></p>]]></description>
			<content:encoded><![CDATA[<p>Safari 5 has brought several solutions for managing lists of open tabs, from the simple (like my <a href="http://brettterpstra.com/2010/06/18/tablinks-safari-extension/">TabLinks extension</a>) to full session-management capabilities (see the beautiful <a href="http://dl.dropbox.com/u/8247646/sessions/index.html">Sessions extension</a>). However, I’ve found I still like using my <a href="http://brettterpstra.com/2010/03/06/saving-safari-browsing-sessions-to-evernote/">EverSave script</a> in many situations, primarily because it allows me to annotate, tag and sync my important sessions for later retrieval. One thing’s been bugging me, though, and that’s the inability to do a mass restore on a tab list (i.e. open them all at once).</p>

<p>When I decided to fix this, the first issue was that when EverSave creates the Evernote note, it lets Evernote convert the list from HTML to Rich Text. Once it’s stored in Rich Text Format (RTF), manipulating it via any shell language, including AppleScript, becomes quite difficult. It’s not impossible, but I quickly decided it wasn’t a route I wanted to wander down. Here’s what I <strong>did</strong> do…
<span id="more-744"></span></p>

<h3>Saving tabs to Evernote</h3>

<p>What I ended up doing was modifying what EverSave stored, and including the actual URL in the visible text of the note. It’s not the prettiest solution, but it’s the only way that this particular system will work. I did my best to minimize the visual presence of the URL using the rudimentary markup that Evernote actually pays attention to. The final product looks like this:</p>

<p><img src="http://cdn2.brettterpstra.com/wp-content/uploads/2010/07/EverSaveRevisedBookmarks1.jpg?9d7bd4" alt="EverSaveRevisedBookmarks.jpg" border="0" width="650" height="93" /></p>

<p>The actual layout is still fully controlled by the _template property in the first line, which is the only line that’s changed from the original script. I’m posting the whole thing again, with this minor revision, for convenience. With a little bit of HTML (remember to escape your double quotes), you can modify the template to look however you like. Just keep in mind that Evernote strips 90% of markup out when it creates the note from your HTML, so stick with basic tags. See the <a href="http://brettterpstra.com/2010/03/06/saving-safari-browsing-sessions-to-evernote/">original EverSave post</a> for a breakdown of the script.</p>

<p>Be sure to continue reading after the script to see how we handle the “restore” functionality.</p>


<div class="wp_syntax"><div class="code"><pre class="applescript"><span class="kw3">property</span> _template : <span class="st0">&quot;&lt;li&gt;&lt;strong&gt;&lt;a href=&quot;</span><span class="re0">%url</span><span class="st0">&quot;&gt;&amp;uArr;&lt;/a&gt; %name&lt;/strong&gt; &lt; &lt;small&gt;%url&lt;/small&gt; &gt;&quot;</span>
&nbsp;
<span class="co1">--search and replace function for template</span>
<span class="kw3">on</span> snr<span class="br0">&#40;</span>tofind, toreplace, TheString<span class="br0">&#41;</span>
	<span class="kw3">set</span> ditd <span class="kw3">to</span> <span class="kw1">text</span> <span class="kw1">item</span> <span class="kw1">delimiters</span>
	<span class="kw3">set</span> <span class="kw1">text</span> <span class="kw1">item</span> <span class="kw1">delimiters</span> <span class="kw3">to</span> tofind
	<span class="kw3">set</span> textItems <span class="kw3">to</span> <span class="kw1">text</span> <span class="kw1">items</span> <span class="kw3">of</span> TheString
	<span class="kw3">set</span> <span class="kw1">text</span> <span class="kw1">item</span> <span class="kw1">delimiters</span> <span class="kw3">to</span> toreplace
	<span class="kw3">if</span> <span class="br0">&#40;</span>class <span class="kw3">of</span> TheString <span class="kw3">is</span> <span class="kw1">string</span><span class="br0">&#41;</span> <span class="kw3">then</span>
		<span class="kw3">set</span> res <span class="kw3">to</span> textItems <span class="kw2">as</span> <span class="kw1">string</span>
	<span class="kw3">else</span> <span class="co1">-- if (class of TheString is Unicode text) then</span>
		<span class="kw3">set</span> res <span class="kw3">to</span> textItems <span class="kw2">as</span> Unicode <span class="kw1">text</span>
	<span class="kw3">end</span> <span class="kw3">if</span>
	<span class="kw3">set</span> <span class="kw1">text</span> <span class="kw1">item</span> <span class="kw1">delimiters</span> <span class="kw3">to</span> ditd
	<span class="kw3">return</span> res
<span class="kw3">end</span> snr
&nbsp;
<span class="kw3">set</span> prettyDate <span class="kw3">to</span> <span class="kw1">do shell script</span> <span class="st0">&quot;date '+%A, %B %d, %Y at %l:%M %p'&quot;</span>
<span class="kw3">set</span> theTitle <span class="kw3">to</span> <span class="st0">&quot;Bookmarks &quot;</span> <span class="sy0">&amp;</span> prettyDate
<span class="kw3">set</span> urlList <span class="kw3">to</span> <span class="st0">&quot;&lt;ul&gt;&quot;</span>
&nbsp;
<span class="kw3">tell</span> <span class="kw1">application</span> <span class="st0">&quot;Safari&quot;</span>
	<span class="kw3">set</span> tabList <span class="kw3">to</span> <span class="kw2">every</span> <span class="kw1">tab</span> <span class="kw3">of</span> <span class="kw2">front</span> <span class="kw1">window</span>
	<span class="kw3">repeat</span> <span class="kw3">with</span> aTab <span class="kw3">in</span> tabList
		<span class="kw3">set</span> aLink <span class="kw3">to</span> _template
		<span class="kw3">set</span> aLink <span class="kw3">to</span> <span class="kw3">my</span> snr<span class="br0">&#40;</span><span class="st0">&quot;%name&quot;</span>, <span class="kw1">name</span> <span class="kw3">of</span> aTab, aLink<span class="br0">&#41;</span>
		<span class="kw3">set</span> aLink <span class="kw3">to</span> <span class="kw3">my</span> snr<span class="br0">&#40;</span><span class="st0">&quot;%url&quot;</span>, URL <span class="kw3">of</span> aTab, aLink<span class="br0">&#41;</span>
		<span class="kw3">set</span> urlList <span class="kw3">to</span> urlList <span class="sy0">&amp;</span> aLink <span class="sy0">&amp;</span> <span class="kw3">return</span>
	<span class="kw3">end</span> <span class="kw3">repeat</span>
<span class="kw3">end</span> <span class="kw3">tell</span>
<span class="kw3">set</span> urlList <span class="kw3">to</span> urlList <span class="sy0">&amp;</span> <span class="st0">&quot;&lt;/ul&gt;&quot;</span>
&nbsp;
<span class="kw3">tell</span> <span class="kw1">application</span> <span class="st0">&quot;Evernote&quot;</span>
	<span class="kw3">set</span> theNote <span class="kw3">to</span> create note <span class="kw3">with</span> html urlList title theTitle notebook <span class="st0">&quot;Bookmarks&quot;</span>
<span class="kw3">end</span> <span class="kw3">tell</span></pre></div></div>


<p>I have this script saved as “EverSave.scpt” in my <code>~/Library/Scripts/Applications/Safari</code> folder (create it if you don’t have it), and launch it using <a href="http://www.red-sweater.com/fastscripts/">FastScripts</a> with a Command-Shift-S shortcut. Safari doesn’t have anything bound to that key-combo, and it’s easy to remember (Save As in most programs).</p>

<h3>Restoring tabs</h3>

<p>This solution makes a few assumptions, but the script is easily customized to handle any differences in your setup. I went with a System Service (Snow Leopard) for the restore function, primarily because it allows me to act directly on selected text in Evernote. It’s a very simple Ruby script that parses the selected text for urls, and then opens any that it finds in sequential order using your default browser. There’s a commented out line if you want to always target Safari directly when opening them, which may be useful in some situations. I use <a href="http://www.choosyosx.com/">Choosy</a>, and have a rule that just directs all of these to Safari. If you have Safari set as your default browser, and that’s where you want to open your links, this will just work as is.</p>

<p>To set up the service:</p>

<ol>
<li>Open Automator and select “Service” as the new file type.</li>
<li>On the right hand side, tell it that “Service receives selected” <strong><em>text</em></strong> in <strong><em>Evernote.app</em></strong> (choose Other… and select Evernote).</li>
<li>Find “Run Shell Script” in the list on the left and drag it into the area on the right.</li>
<li>Set the Shell dropdown to /usr/bin/ruby</li>
<li>Insert the following code, and feel free to modify</li>
<li>Save the result as “EverRestore”</li>
<li>Assign a shortcut key, if desired, in System Preferences &gt; Keyboard &gt; Keyboard Shortcuts &gt; Services</li>
</ol>

<p>Here’s the code for the service:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby">ARGF.<span class="me1">each</span> <span class="kw1">do</span> <span class="sy0">|</span>f<span class="sy0">|</span>
    links = f.<span class="me1">scan</span> <span class="sy0">/&lt;</span> <span class="br0">&#40;</span>https?:<span class="sy0">//</span>.<span class="sy0">*</span>?<span class="br0">&#41;</span> <span class="sy0">&gt;/</span>mi
    <span class="co1"># The above scans specifically for the angle brackets in my template. </span>
    <span class="co1"># If you remove those from the output of EverSave, be sure to update</span>
    <span class="co1"># the regular expression accordingly.</span>
    <span class="kw1">if</span> links.<span class="me1">empty</span>? <span class="kw1">then</span>
        <span class="kw3">exit</span>
    <span class="kw1">else</span>
        links.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>link<span class="sy0">|</span> <span class="sy0">%</span>x<span class="br0">&#123;</span>osascript <span class="sy0">-</span>e <span class="sy0">&amp;</span><span class="co1">#x27;open location &quot;#{link[0]}&quot;&amp;#x27;}}</span>
        <span class="co1"># links.each {|link| %x{osascript -e &amp;#x27;tell application &quot;Safari&quot; to open location &quot;#{link[0]}&quot;&amp;#x27;} }</span>
    <span class="kw1">end</span>
<span class="kw1">end</span></pre></div></div>


<p>The simple regular expression in line 2 does scan specifically for the angle brackets I used in the new EverSave template. That just relieves some complexity. If you want a regular expression that doesn’t require the angle brackets, try replacing line 2 with this:</p>


<div class="wp_syntax"><div class="code"><pre class="ruby">links = f.<span class="me1">scan</span> <span class="sy0">/</span><span class="br0">&#40;</span>https?:<span class="sy0">//</span><span class="br0">&#40;</span><span class="br0">&#91;</span>^s<span class="st0">&quot;,;]+)..{2,4}(/[^s&quot;</span>,;!<span class="br0">&#93;</span><span class="sy0">+</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">/</span>mi</pre></div></div>


<p>Once it’s saved in Automator, it should be available when you select text in Evernote. If there are visible URLs in the selected text, running this Service will open them in tabs in Safari (or your default browser). You can selectively open certain urls by only selecting the lines that contain the ones you want to open. Non-contiguous selections will require a little text editing, of course.</p>

<h3>Not as hard as it looks… really.</h3>

<p>The explanation got a little long, and probably seems unnecessarily complex. The fact is, I can save a Safari browsing session with one key combo, edit, annotate and tag it (if I want to), then restore it later by highlighting and typing a new command combination. It’s actually quite convenient, and fairly bulletproof. I’d love to hear how you use it, or what you’re doing instead!</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/antique-safari-reader-hack-update-with-evernote-goodness/' rel='bookmark' title='Antique Safari Reader hack update with Evernote goodness'>Antique Safari Reader hack update with Evernote goodness</a></li>
<li><a href='http://brettterpstra.com/clippable-to-evernote-snow-leopard-service/' rel='bookmark' title='Clippable to Evernote Snow Leopard Service'>Clippable to Evernote Snow Leopard Service</a></li>
<li><a href='http://brettterpstra.com/save-safari-tabs-to-instapaper/' rel='bookmark' title='Save Safari tabs to Instapaper'>Save Safari tabs to Instapaper</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/eversave-revisited-now-with-session-restore/">EverSave revisited, now with session restore!</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/eversave-revisited-now-with-session-restore/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A System Service for to. url shortening</title>
		<link>http://brettterpstra.com/a-system-service-for-to-url-shortening/</link>
		<comments>http://brettterpstra.com/a-system-service-for-to-url-shortening/#comments</comments>
		<pubDate>Thu, 29 Apr 2010 02:03:48 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[snow leopard]]></category>
		<category><![CDATA[System Service]]></category>
		<category><![CDATA[url shortener]]></category>
		<category><![CDATA[utility]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=399</guid>
		<description><![CDATA[<p>I’m fascinated by http://to. It’s a url shortener with no TLD. Some browsers, and apparently some DNS setups, don’t like the urls it creates (they want a .com or .org or anything at the end), so it’s not exactly in heavy usage. Still, I wish they had an API. In lieu of that, here’s a quick Ruby script that will&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/a-system-service-for-to-url-shortening/">A System Service for to. url shortening</a></p>]]></description>
			<content:encoded><![CDATA[<p>I’m fascinated by <a href="http://to.">http://to</a>. It’s a url shortener with no <acronym title="Top Level Domain">TLD</acronym>. Some browsers, and apparently some DNS setups, don’t like the urls it creates (they want a .com or .org or <em>anything</em> at the end), so it’s not exactly in heavy usage. Still, I wish they had an API. In lieu of that, here’s a quick Ruby script that will run on a stock OS X install as a System Service. It’s so simple that I’m not even going to package it up… It’ll be a good chance to show the steps for creating your own utilities using <a href="http://macosautomation.com/services/index.html">Snow Leopard Services</a>:</p>

<ul>
<li>Open Automator and choose “Service” from the first menu.</li>
<li>Tell it that the service “receives text” in “any application”. </li>
<li>Drag the “Run Shell Script” action from the left side. </li>
<li>Set the Shell to Ruby</li>
<li>Paste in the code below (or something of your own, hopefully far more interesting)</li>
<li>Save it with an intuitive name</li>
<li>Use it.</li>
</ul>


<div class="wp_syntax"><div class="code"><pre class="ruby"><span class="kw3">require</span> <span class="st0">'net/http'</span>
<span class="kw3">require</span> <span class="st0">'cgi'</span>
&nbsp;
input = STDIN.<span class="me1">read</span>
http = <span class="re2">Net::HTTP</span>.<span class="me1">new</span><span class="br0">&#40;</span><span class="st0">'to.'</span><span class="br0">&#41;</span>
path = <span class="st0">'/'</span>
&nbsp;
data = <span class="st0">&quot;url=#{CGI.escape(input.strip)}&quot;</span>
headers = <span class="br0">&#123;</span><span class="st0">'Content-Type'</span> <span class="sy0">=&gt;</span> <span class="st0">'application/x-www-form-urlencoded'</span><span class="br0">&#125;</span>
&nbsp;
resp, data = http.<span class="me1">post</span><span class="br0">&#40;</span>path, data, headers<span class="br0">&#41;</span>
&nbsp;
<span class="kw1">if</span> resp.<span class="me1">code</span>.<span class="me1">to_i</span> == <span class="nu0">200</span>
  <span class="kw3">print</span> data.<span class="kw3">split</span><span class="br0">&#40;</span><span class="sy0">/</span>value=<span class="st0">&quot;/)[1].split(/&quot;</span><span class="sy0">/</span><span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>
<span class="kw1">else</span>
  <span class="kw3">print</span> input
<span class="kw1">end</span></pre></div></div>


<p>Basically, anything you can do to or with text or files using a major scripting language, you can make into a Snow Leopard service. Now that I’ve set the bar this low, I’d love to see what new Services everyone else is cooking up!</p>

<p><strong>Update:</strong> <del datetime="2010-04-29T03:34:55+00:00">Yeah, that didn’t work out so well. It works sometimes, but leaves url parameters in the shortened url half the time. I haven’t figured out why, but I’ll leave it up and see if someone can point out the error of my ways…</del><ins datetime="2010-04-29T03:34:55+00:00">Fixed it, just neglected to notice it needed a POST, not a GET</ins></p>

<p><strong>Update 2:</strong> Here, this one’s shorter and more useful :)</p>


<div class="wp_syntax"><div class="code"><pre class="ruby"><span class="kw3">require</span> <span class="st0">'open-uri'</span>
<span class="kw3">require</span> <span class="st0">'cgi'</span>
&nbsp;
input = STDIN.<span class="me1">read</span>
<span class="kw3">print</span> <span class="kw3">open</span><span class="br0">&#40;</span><span class="st0">&quot;http://is.gd/api.php?longurl=#{CGI.escape(input.strip)}&quot;</span><span class="br0">&#41;</span>.<span class="me1">read</span></pre></div></div>

<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/is-your-url-too-short-try-our-system-free/' rel='bookmark' title='Is your URL too short? Try our system, free!'>Is your URL too short? Try our system, free!</a></li>
<li><a href='http://brettterpstra.com/textexpander-bit-ly-with-authentication/' rel='bookmark' title='TextExpander: bit.ly with authentication'>TextExpander: bit.ly with authentication</a></li>
<li><a href='http://brettterpstra.com/textexpander-experiments/' rel='bookmark' title='TextExpander experiments'>TextExpander experiments</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/a-system-service-for-to-url-shortening/">A System Service for to. url shortening</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/a-system-service-for-to-url-shortening/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Updated: Songza Lucky Link Service</title>
		<link>http://brettterpstra.com/updated-songza-lucky-link-service/</link>
		<comments>http://brettterpstra.com/updated-songza-lucky-link-service/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 03:25:25 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[snow leopard]]></category>
		<category><![CDATA[songza]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=338</guid>
		<description><![CDATA[<p>Songza.fm has moved to Songza.org, so I’ve rewritten the old Songza Lucky Link Service for Snow Leopard to match. This new version of the service runs without dependencies, so it should work for any Snow Leopard setup right out of the box. It’s a bit silly, but what it does is take your selected text and run it as a&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/updated-songza-lucky-link-service/">Updated: Songza Lucky Link Service</a></p>]]></description>
			<content:encoded><![CDATA[<p>Songza.fm has moved to Songza.org, so I’ve rewritten the <a href="http://brettterpstra.com/2009/11/12/songza-lucky-link-service/">old Songza Lucky Link Service</a> for Snow Leopard to match. This new version of the service runs without dependencies, so it should work for any Snow Leopard setup right out of the box. It’s a bit silly, but what it does is take your selected text and run it as a query on Songza.org, parse for the first result (if there are any), shorten that link and insert it after your selected text. A fast, easy way to punctuate your obscure music references in emails and on the web. Have fun, and join me in hoping for the Songza API to blossom into something we can really sink our scripts into!</p>

<p>To install, just download the file below, unzip it (double click), and move it into <code>[your username]/Library/Services</code>. To use it, select text in any Cocoa app (Safari, Mail, and most Mac apps) and look under the application menu in the menubar for the Services submenu. Trigger it from there, or just right click on your selected text and you should get the same services menu as a contextual menu item. If you’re feeling clever, go into the Keyboard preferences pane, choose Keyboard Shortcuts -&gt; Services and double click the blank space to the right of the service to assign a hotkey. As long as that hotkey isn’t already assigned by the application your using, you can trigger the service with it any time you have text selected.</p>

<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/SongzaLuckyLinkSLService.zip?9d7bd4" title="Download Songza Lucky Link Service (80)"><img src="http://brettterpstra.com/wp-content/images/serviceicon.jpg?9d7bd4" alt="download image for Songza Lucky Link Service" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/SongzaLuckyLinkSLService.zip?9d7bd4" title="Download Songza Lucky Link Service (80)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/SongzaLuckyLinkSLService.zip?9d7bd4" title="Download Songza Lucky Link Service (80)">Songza Lucky Link Service</a> — A Snow Leopard Service to generate a shortened url to the first result of a Songza.org search for the selected text. The text will remain, but it will have the result in parenthesis after it. Uses a built-in html parser to scrape the results, at least until Songza provides an API. <a href="http://brettterpstra.com/2010/03/20/updated-songza-lucky-link-service/">More Info</a></p></div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/songza-lucky-link-service/' rel='bookmark' title='Songza Lucky Link Service'>Songza Lucky Link Service</a></li>
<li><a href='http://brettterpstra.com/songza-is-back/' rel='bookmark' title='Songza is back!'>Songza is back!</a></li>
<li><a href='http://brettterpstra.com/auto-link-text-service-updated/' rel='bookmark' title='Auto-link text service updated'>Auto-link text service updated</a></li>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/updated-songza-lucky-link-service/">Updated: Songza Lucky Link Service</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/updated-songza-lucky-link-service/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic (Feed is rejected)
Page Caching using disk: enhanced
Database Caching 37/183 queries in 0.747 seconds using xcache
Object Caching 4513/4690 objects using xcache
Content Delivery Network via cdn2.brettterpstra.com

Served from: brettterpstra.com @ 2012-02-09 17:36:46 -->
