<?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 Terpstrascripting - Brett Terpstra</title>
	<atom:link href="http://brettterpstra.com/tag/scripting/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>A simple but handy Bash function: console</title>
		<link>http://brettterpstra.com/a-simple-but-handy-bash-function-console/</link>
		<comments>http://brettterpstra.com/a-simple-but-handy-bash-function-console/#comments</comments>
		<pubDate>Wed, 28 Dec 2011 09:30:39 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[terminal]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3487</guid>
		<description><![CDATA[<p>Here’s a quick riff on an older bash alias I use which will allow you to easily scan system messages from Terminal. I’ve long had an alias in my ~/.bash_profile called console. It simply tailed the system log with ‘alias console=‘tail –f /var/log/system.log’. Bam I decided to amp it up a little for added convenience. The function below allows me&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/a-simple-but-handy-bash-function-console/">A simple but handy Bash function: console</a></p>]]></description>
			<content:encoded><![CDATA[<p>Here’s a quick riff on an older bash alias I use which will allow you to easily scan system messages from Terminal.</p>

<p>I’ve long had an alias in my <code>~/.bash_profile</code> called <code>console</code>. It simply tailed the system log with ‘alias console=‘tail –f /var/log/system.log’.</p>

<h3>Bam</h3>

<p>I decided to amp it up a little for added convenience. The function below allows me to add additional arguments which are translated into a regular expression for filtering the log output. Arguments, separated by spaces on the command line, are joined into a regular expression as OR matches. You can specify as many as you like to track each as a keyword. It’s case insensitive and you can use basic regular expression syntax in each parameter. Examples:</p>

<pre><code>$ console byword

$ console usbmuxd servermgrd

$ console mark(ed|y) multimarkdown composer
</code></pre>

<p><code>console</code> with no arguments will still just tail the log with no filter.</p>

<h3>The function</h3>

<p>Just stick this in your <code>~/.bash_profile</code> file, run <code>. ~/.bash_profile</code> and try it out.</p>

<pre><code>function console () {
  if [[ $# &gt; 0 ]]; then
    query=$(echo "$*"|tr -s ' ' '|')
    tail -f /var/log/system.log|grep -i --color=auto -E "$query"
  else
    tail -f /var/log/system.log
  fi
}
</code></pre>

<p>If you want to track more than just the <code>system.log</code> file, you can just add additional filenames, separated by a space, after system.log for each <code>tail</code> command in the function.</p>

<p>There, that was handy.</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/fk-a-useful-bash-function/' rel='bookmark' title='fk: a useful bash function'>fk: a useful bash function</a></li>
<li><a href='http://brettterpstra.com/oft-bash-function-for-opening-a-specific-filetype/' rel='bookmark' title='oft: Bash function for opening a specific filetype'>oft: Bash function for opening a specific filetype</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/a-simple-but-handy-bash-function-console/">A simple but handy Bash function: console</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/a-simple-but-handy-bash-function-console/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>na: per-project todos in Terminal</title>
		<link>http://brettterpstra.com/na-per-project-todos-in-terminal/</link>
		<comments>http://brettterpstra.com/na-per-project-todos-in-terminal/#comments</comments>
		<pubDate>Sat, 24 Dec 2011 14:00:06 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[bash]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[TaskPaper]]></category>
		<category><![CDATA[terminal]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3421</guid>
		<description><![CDATA[<p>As I’ve mentioned before, I keep todo.taskpaper files in my web and code project folders. These allow me to keep track of bugs, ideas, notes, etc., and the archive it creates helps me remember what I did, when I did it and how it worked. I like having them separated per project; it’s the way my one-track mind works. I&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/na-per-project-todos-in-terminal/">na: per-project todos in Terminal</a></p>]]></description>
			<content:encoded><![CDATA[<p>As I’ve mentioned before, I keep todo.taskpaper files in my web and code project folders. These allow me to keep track of bugs, ideas, notes, etc., and the archive it creates helps me remember what I did, when I did it and how it worked. I like having them separated per project; it’s the way my one-track mind works. I like the plain-text format because I can use any variety of methods (including <a href="http://www.hogbaysoftware.com/products/taskpaper">TaskPaper</a> itself) to manipulate and quickly update the files. This gave me the idea to have Terminal just notify me of current todos whenever I switched to a project. Thus, <code>na</code> was born. Whether or not it’s useful to anyone else remains to be seen, but I figured I’d share it anyway.</p>

<p>Yesterday at 5:30pm, this little project was working fine with about eight lines of code. Then I had an idea or two, and by morning it was 160 lines of code. It definitely got out of hand, but I rather like the final product. The bulk of the script is straight bash and UN*X commands, but I shelled a lot of the more complex string handling out to Ruby. I’m too lazy to deal with <code>awk</code> and <code>sed</code> past a certain point.</p>

<p>Feel free to skip to <a href="https://github.com/ttscoff/na">the <code>na</code> GitHub repo</a>, peek at the readme.md file and start playing. I welcome any revisions/iterations of this, so feel free to fork and let me know what you do with it!</p>

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

<h3>Meet “na”</h3>

<p><code>na</code> is a bash function designed to make it easy to see what your next actions are for any project, right from the command line. It works with TaskPaper-format files (but any plain text format will do), looking for @na tags (or whatever you specify) in todo files in your current folder. It can also auto-display next actions when you enter a project directory, automatically locating any todo files and listing their next actions when you <code>cd</code> to the project (optionally recursive).</p>

<h3>Features</h3>

<p>You can list next actions in files in the current directory by typing <code>na</code>. By default, <code>na</code> looks for “.taskpaper” files and extracts items tagged “@na” and not “@done”. All of these can be changed in the configuration.</p>

<h4>Easy matching</h4>

<p><code>na</code> features intelligent project matching. Every time it locates a todo file, it adds the project to the database. Once a project is recorded, you can list its actions by using any portion of the parent directories names. If your project is in “~/Sites/dev/markedapp,” you could quickly list its next actions by typing <code>na dev mark</code>. It will always look for the shortest match.</p>

<h4>Recursion</h4>

<p><code>na</code> can also recurse subdirectories to find all todo files in child folders as well. Use the <code>-r</code> switch to do a recursive search on the current directory. <code>na -r</code> with no arguments will recurse from your current location, looking for todo files in all subdirectories. Maximum depth for recursion can be controlled in the config (default is 4). <code>na -r</code> can take a path or project title fragments as arguments as well, and will recurse from the matched directory. A configuration option allows you to have the auto-display recurse by default.</p>

<h4>Adding todos</h4>

<p>You can also quickly add todo items from the command line with the <code>-a</code> switch. The script will look for a file in the current directory called todo.taskpaper (or whatever extension you’ve set). If found, it will try to locate an “Inbox:” project, or create one if it doesn’t exist. Any arguments after <code>-a</code> will be combined to create a new task in TaskPaper format. They will automatically be assigned as next actions (tagged “@na”) and will show up when <code>na</code> lists the tasks for the project.</p>

<p>More details and usage examples (as well as the download) <a href="https://github.com/ttscoff/na">on the GitHub page</a>.</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/totally-taskpaper/' rel='bookmark' title='Totally TaskPaper'>Totally TaskPaper</a></li>
<li><a href='http://brettterpstra.com/quick-tip-throttling-parallel-batch-processes-in-terminal/' rel='bookmark' title='Quick Tip: throttling parallel batch processes in Terminal'>Quick Tip: throttling parallel batch processes in Terminal</a></li>
<li><a href='http://brettterpstra.com/quick-link-terminal-navigation-utilities/' rel='bookmark' title='Quick Link: Terminal navigation utilities'>Quick Link: Terminal navigation utilities</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/na-per-project-todos-in-terminal/">na: per-project todos in Terminal</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/na-per-project-todos-in-terminal/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>A little KeyBinding sanity</title>
		<link>http://brettterpstra.com/a-little-keybinding-sanity/</link>
		<comments>http://brettterpstra.com/a-little-keybinding-sanity/#comments</comments>
		<pubDate>Thu, 22 Dec 2011 02:03:11 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[keybindings]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3415</guid>
		<description><![CDATA[<p>I finally got around to writing a script to auto-generate the documentation for my DefaultKeyBinding.dict file. The script now reads my comments in the file and creates tables of keystrokes and descriptions ready for GitHub. From now on, my fickle changes will be reflected in the readme.md file in the repo and the keystrokes will stay current. You can see&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/a-little-keybinding-sanity/">A little KeyBinding sanity</a></p>]]></description>
			<content:encoded><![CDATA[<p>I finally got around to writing a script to auto-generate the documentation for my <a href="https://github.com/ttscoff/KeyBindings">DefaultKeyBinding.dict</a> file. The script now reads my comments in the file and creates tables of keystrokes and descriptions ready for GitHub. From now on, my fickle changes will be reflected in the readme.md file in the repo and the keystrokes will stay current. You can see the <a href="https://github.com/ttscoff/KeyBindings/blob/master/readme.md">current output here</a>.</p>

<p>If you’ve taken off with <a href="http://brettterpstra.com/the-keys-that-bind-keybinding-madness-part-2/">KeyBindings</a> already and your file wildly diverges from mine, the script is available for use by anyone. It requires a certain format in the file (I built it specifically for my own needs), but a little modification and you should be able to generate quick cheat-sheets for your own bindings.</p>

<p>You can find the script in the <a href="https://github.com/ttscoff/KeyBindings">KeyBindings repo</a> (it’s called <code>document_keybindings.rb</code>). You’ll want to modify the various sections of the output, so you’ll need to know a little Ruby to dink around with it. It’s not a bulletproof script by any means, but if you know a few regular expressions and some basic logic you’ll be able to make it do what you want. Note that by default it reads from “DefaultKeyBinding.dict” in the same directory as the script, and writes out to “readme.md” (in the same directory).</p>

<h3>.dict file format</h3>

<p>The basic comment/command format is:</p>

<pre><code>// &gt; defaults write -g NSTextKillRingSize -string 6
// replace yank: command with yankAndSelect for use with the kill ring
"^y" = (yankAndSelect:);
</code></pre>

<ul>
<li>Lines beginning with “// &gt;” are added as parenthetical notes to the next command’s description</li>
<li>Lines beginning with “// TODO” are ignored</li>
<li>The description of the command comes before the line it’s defined on</li>
<li>I doesn’t handle free-spaced commands yet, command definitions should be on a single line (for now)</li>
</ul>

<p>Groups are defined similarly:</p>

<pre><code>"^@c" = { // Commenting commands
  // comment with "//"
  "/" = (setMark:, moveToBeginningOfParagraph:, insertText:, "// ", swapWithMark:, moveRight:, moveRight:, moveRight:);
  // comment with "#"
  "\\" = (setMark:, moveToBeginningOfParagraph:, insertText:, "# ", swapWithMark:, moveRight:, moveRight:);
};
</code></pre>

<ul>
<li>The title of the group is on the same line as the starting bracket</li>
<li>Commands within the group will be prefixed with the group’s key combination in the output</li>
</ul>

<p>Any top-level commands (not in a group) will be gathered and output at the top of the output. You can modify the script to title that table any way you like.</p>

<p>The output table is currently in MultiMarkdown format but converted to HTML (using <code>/usr/local/bin/multimarkdown</code>, so you’ll need that installed) before writing to the ‘readme.md’ file. You can change or remove all of the prefixed verbage just by editing the INTRO variable.</p>

<p>Hopefully this will help keep things cleaner and minimize the number of explanations I have to send out in emails. Something about sharing a complicated trick and then modifying the steps without updating the documentation seems to throw people off. Fancy that.</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/an-average-morning/' rel='bookmark' title='An average morning'>An average morning</a></li>
<li><a href='http://brettterpstra.com/introducing-the-marked-bonus-pack/' rel='bookmark' title='Introducing the Marked Bonus Pack'>Introducing the Marked Bonus Pack</a></li>
<li><a href='http://brettterpstra.com/keybinding-madness/' rel='bookmark' title='KeyBinding madness'>KeyBinding madness</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-little-keybinding-sanity/">A little KeyBinding sanity</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/a-little-keybinding-sanity/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>“Open URLs” Dropzone Destination</title>
		<link>http://brettterpstra.com/open-urls-dropzone-destination/</link>
		<comments>http://brettterpstra.com/open-urls-dropzone-destination/#comments</comments>
		<pubDate>Mon, 21 Nov 2011 16:30:01 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[dropzone]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3212</guid>
		<description><![CDATA[<p>I just added a pull request for my latest Dropzone (review) Destination. It’s called “Open URLs,” and with it you can open text urls from any number of text files, drag text straight from any application, or just click it to scan your clipboard. The files, text or clipboard contents are scanned for any http(s) links and they’re sent to&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/open-urls-dropzone-destination/">“Open URLs” Dropzone Destination</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/11/1321804820_Bookmarks_Black-2.png?9d7bd4" alt="Open URLs icon" title="1321804820_Bookmarks_Black-2" width="256" height="256" class="alignright size-full wp-image-3224" />I just added a pull request for my latest <a href="http://aptonic.com/">Dropzone</a> (<a href="http://brettterpstra.com/app-review-dropzone/">review</a>) Destination. It’s called “Open URLs,” and with it you can open text urls from any number of text files, drag text straight from any application, or just click it to scan your clipboard. The files, text or clipboard contents are scanned for any http(s) links and they’re sent to your default browser using the system <code>open</code> command.</p>

<p>“Open URLs” is ideal if you collect browsing “sessions” in text files or notes in any format (possibly using tools such as <a href="http://brettterpstra.com/tablinks-2-0/">TabLinks</a> or <a href="http://brettterpstra.com/eversave-revisited-now-with-session-restore/">EverSave</a>). I often use TabLinks to save a collection of same-subject links to a note in <a href="http://brettterpstra.com/project/nvalt/">nvALT</a> and then drag and drop the text to re-open the whole session. It’s also very handy when someone emails you a list of urls that you want to open all at once (e.g. a design project with multiple versions and they couldn’t be bothered to make it a Dropbox gallery). If you’re on a page with a list of links and you want to open them all in tabs quickly, just view source, select the section with the links and drag the selection to the Destination in Dropzone. It will ignore duplicates and open one tab per unique link.</p>

<p>I expect this Destination will be available soon from the <a href="https://github.com/aptonic/dropzone-user-scripts">GitHub repo</a>, but you can download it directly below if you’re using Dropzone and it happens to sound useful. <strong>Update:</strong> before I even got this post out, John Winter of Aptonic got this Destination on the <a href="http://aptonic.com/extend.php">Extend page</a> of the Dropzone website. You can grab it there, too!</p>

<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/OpenURLS.dropzone.zip?9d7bd4" title="Download Open URLs Dropzone Destination (41)"><img src="http://cdn2.brettterpstra.com/wp-content/uploads/downloads/thumbnails/2011/11/1321804820_Bookmarks_Black-2.png?9d7bd4" alt="download image for Open URLs Dropzone Destination" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/OpenURLS.dropzone.zip?9d7bd4" title="Download Open URLs Dropzone Destination (41)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/OpenURLS.dropzone.zip?9d7bd4" title="Download Open URLs Dropzone Destination (41)">Open URLs Dropzone Destination</a> — A Destination for Dropzone that allows you to drag files, text or click to scan your clipboard. All links found in the text are sent to your default browser to open in tabs. <a href="http://brettterpstra.com/open-urls-dropzone-destination/">More Info</a></p></div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/app-review-dropzone/' rel='bookmark' title='App Review: Dropzone'>App Review: Dropzone</a></li>
<li><a href='http://brettterpstra.com/app-giveaway-dropzone/' rel='bookmark' title='Mac App Giveaway: Dropzone'>Mac App Giveaway: Dropzone</a></li>
<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>
</ol></p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/open-urls-dropzone-destination/">“Open URLs” Dropzone Destination</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/open-urls-dropzone-destination/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Marked scripts: nvALT, Evernote, MarsEdit, Scrivener</title>
		<link>http://brettterpstra.com/marked-scripts-nvalt-evernote-marsedit-scrivener/</link>
		<comments>http://brettterpstra.com/marked-scripts-nvalt-evernote-marsedit-scrivener/#comments</comments>
		<pubDate>Tue, 15 Nov 2011 03:38:38 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[marked]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3177</guid>
		<description><![CDATA[<p>Thus far, Marked has had a great reception and has, overall, worked superbly with a wide range of text editors. I frequently get requests for integration with more complex editors, but have been unable to fulfill them because Marked requires an actual text file to watch. To try and fix this situation, I’ve been scripting “watchers” for various applications which&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/marked-scripts-nvalt-evernote-marsedit-scrivener/">Marked scripts: nvALT, Evernote, MarsEdit, Scrivener</a></p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://markedapp.com"><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  src="http://cdn2.brettterpstra.com/wp-content/uploads/2011/11/newmarkedlogo.png?9d7bd4" alt="" title="newmarkedlogo" width="244" height="281" class="alignright size-full wp-image-3178" /></a>Thus far, <a href="http://markedapp.com">Marked</a> has had a great reception and has, overall, worked superbly with a wide range of text editors. I frequently get requests for integration with more complex editors, but have been unable to fulfill them because Marked requires an actual text file to watch. To try and fix this situation, I’ve been scripting “watchers” for various applications which embed their files inside of bundles or otherwise obscure the actual content files from Spotlight.</p>

<p>I’ve created scripts for <a href="http://notational.net/">Notational Velocity</a>/<a href="http://brettterpstra.com/project/nvalt/">nvALT</a>, <a href="http://www.red-sweater.com/marsedit/">MarsEdit</a>, <a href="http://www.literatureandlatte.com/">Scrivener</a> and <a href="http://www.evernote.com/">Evernote</a>. The scripts will be part of the <a href="http://support.markedapp.com/kb/how-to-tips-and-tricks/marked-bonus-pack-scripts-commands-and-bundles">Marked Bonus pack</a>, but are also available as a separate download here (see the end of the post). I would eventually like to incorporate the functionality directly into Marked, but it will take some time to add the necessary configuration options and make it an elegant fit.</p>

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

<p>The scripts work by using timestamps and polling with Ruby to detect changes within certain files and directories (varies from script to script)<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>. The Evernote, nvALT and MarsEdit scripts can be run without arguments (or as LaunchAgents). The Scrivener script requires the path to the <code>.scriv</code> file for your project as the only argument.</p>

<p>The preview contents are always saved to ‘Marked Preview.md’ in your home folder. When you first start, you may need to create this file manually with a text editor and save it to your home folder. Once the scripts have run once, the file will exist and you can open it in Marked any time you’re working in a “watched” application.</p>

<p>All of this was inspired by <a href="https://gist.github.com/1355558">this gist</a> by <a href="https://github.com/myfreeweb">myfreeweb</a>. His method uses fsevents and Python, which is definitely more elegant in many cases. I switched it over to use Ruby and timestamps because I’m pretty lame with Python right now. If you want to take the basic ideas and convert them to use fsevents, please share! I’ll be happy to host and credit (or just link, if you prefer) any submissions.</p>

<p>I’m certainly taking requests for any other editors you’d like to have “watched,” so drop your vote in the comments.</p>

<h3>Notes:</h3>

<p>For all of these scripts, the easiest way to use them is to put them in a convenient folder (I use <code>~/scripts</code>) and run <code>chmod a+x path/to/script.rb</code> to make them executable. With the exception of the Scrivener script (<code>scrivwatch.rb</code>), you can then just type the path and script name (e.g. <code>~/scripts/everwatch.rb</code>) and hit Enter. They will run and watch for changes in their specific application until you cancel the command by typing <code>Control-c</code>.</p>

<p>The scripts will create a file in your home directory (modifiable in the script) called ‘Marked Preview.md’. Open that file in Marked; Marked will watch that file for changes that the scripts make.</p>

<p>You can create LaunchAgents for any of these (except, again, Scrivener) and run them automatically in the background if you know what you’re doing. If you don’t, you can still use an app like <a href="http://www.peterborgapps.com/lingon/">Lingon</a> to do it.</p>

<h4>Evernote (everwatch.rb)</h4>

<p>To keep the ‘Marked Preview.md’ file synced with whatever note you’re currently editing in <a href="http://www.evernote.com/">Evernote</a>, start the script by running <code>~/path/to/everwatch.rb</code> in Terminal. The script watches for changes to timestamps on any directory in Evernote’s data folder. This shouldn’t need to be adjusted. To update Marked, you’ll need to have “~/Marked Preview.md” open and then hit “Command-S” in your Evernote note. The autosave on Evernote will work, but it takes longer.</p>

<p>The HTML of the note is captured via AppleScript and run through <code>textutil</code> to remove the HTML formatting. This means that embedded images won’t come through, but those probably would have broken anyway. The script is specifically expecting you to write your notes in Markdown. If you’re not, I’m not sure why you’d want a Marked preview anyway…</p>

<p>Even with “Command-S” there’s still a 4–5 second delay on the update, as it takes a bit for Evernote to write out to the file, the script to poll through and notice the change, the content to be pulled via AppleScript and written to the preview file and then for Marked to pick up on the change there. Considering all of that, 4–5 seconds isn’t too bad. If someone can think of a faster way, I’m certainly open to it.</p>

<h4>Scrivener (scrivwatch.rb)</h4>

<p>The <a href="http://www.literatureandlatte.com/">Scrivener</a> script watches the RTF files that Scrivener keeps within the project as you write. If you set Scrivener’s preferences to auto-save 1 second after you stop typing, Marked will stay pretty snappy on the updates without any further intervention.</p>

<p>To launch (assuming you made the script executable as detailed at the beginning of this section), open Terminal and type <code>path/to/scrivwatch.rb /path/to/YourDocument.scriv</code>. Example: <code>~/scripts/scrivwatch ~/Documents/Thesis.scriv</code>. The script will take it from there and run until you interrupt with <code>Control-c</code>.</p>

<p>The files Scrivener stores are Rich Text Format, so Marked can’t view their contents directly. The script runs the most recently-edited file through <code>textutil</code> to convert from RTF to text. That gets passed to the ‘Marked Preview.md’ file for Marked to display. Only the portion of your Scrivener document that you’re currently editing will be displayed. I played with concatenating the whole document for preview, but it’s not easy to determine the order to display all of the individual files in. Again, if anyone has further ideas, please share!</p>

<h4>MarsEdit (marswatch.rb)</h4>

<p>Thanks to Daniel Jalkut for an assist with this one. It watches the <a href="http://www.red-sweater.com/marsedit/">MarsEdit</a> autosave folder for any changes, and then uses AppleScript to get the full contents of the editor (post <em>and</em> continued) when one is detected. Because the autosave can be a bit slow on the draw, it continues updating every second for 10 seconds, whether there’s a change or not. If no more changes are detected within 10 seconds, it chills out in the background until the next one is detected.</p>

<p>Run <code>marswatch.rb</code> to start polling for changes, open ‘Marked Preview.md‘ from your home folder and Marked should start updating the preview automatically as you make changes in a MarsEdit post.</p>

<h4>Notational Velocity/nvALT (nvwatch.rb)</h4>

<p>If you’re using <a href="http://notational.net/">Notational Velocity</a> (or my fork, <a href="http://brettterpstra.com/project/nvalt/">nvALT</a>), you can tell it to save your notes as text files on your drive. This script will watch these text files for updates, then display the contents of the most recently-edited note. It’s a workable solution, at least until I get better integration worked into nvALT directly.</p>

<p>You need to configure the script to point to your chosen folder for note storage, and if you’re using any unique extension, you’ll need to add to or modify the list in the script. It should be pretty obvious what needs to be set if you look at the top of the script.</p>

<h3>Download</h3>

<p>I’m sure I forgot some details in this writeup, so if you have any questions, leave a comment and I’ll add information as needed.</p>

<p>The most recent versions of the watcher scripts are now included the the <a href="http://support.markedapp.com/kb/how-to-tips-and-tricks/marked-bonus-pack-scripts-commands-and-bundles">Marked Bonus Pack</a>.</p>

<p>You can find out more about Marked at the <a href="http://markedapp.com">Marked website</a>.</p>

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

<li id="fn:1">
<p>Related tip: you can use <code>sudo opensnoop -p PID</code> (where PID is the PID of the application you’re working with) to view all files that the application touches. It’s a good way to figure out what to watch when working on scripts like these. <a href="#fnref:1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/preview-a-full-scrivener-document-in-marked-live/' rel='bookmark' title='Preview a full Scrivener document in Marked, live'>Preview a full Scrivener document in Marked, live</a></li>
<li><a href='http://brettterpstra.com/scrivwatcher-droplet-an-easier-live-scrivener-preview/' rel='bookmark' title='ScrivWatcher droplet, an easier live Scrivener preview'>ScrivWatcher droplet, an easier live Scrivener preview</a></li>
<li><a href='http://brettterpstra.com/the-second-marked-giveaway/' rel='bookmark' title='The second Marked giveaway!'>The second Marked giveaway!</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/marked-scripts-nvalt-evernote-marsedit-scrivener/">Marked scripts: nvALT, Evernote, MarsEdit, Scrivener</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/marked-scripts-nvalt-evernote-marsedit-scrivener/feed/</wfw:commentRss>
		<slash:comments>15</slash:comments>
		</item>
		<item>
		<title>Geeklet: Top RAM Processes</title>
		<link>http://brettterpstra.com/geeklet-top-ram-processes/</link>
		<comments>http://brettterpstra.com/geeklet-top-ram-processes/#comments</comments>
		<pubDate>Wed, 09 Nov 2011 13:30:29 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[geeklet]]></category>
		<category><![CDATA[geektool]]></category>
		<category><![CDATA[nerdtool]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3070</guid>
		<description><![CDATA[<p>This next geeklet is quite similar to the Top CPU Processes geeklet I last shared. It finds the apps and processes with the biggest memory footprint on your system and lists the top 10. The output looks like: Top RAM processes WebProcess 926.62M Mail 360.05M Safari 211.48M iTunes 206.38M Finder 180.80M Skype 143.15M WindowServer 137.12M LaunchBar 135.71M mds 118.14M Reeder&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/geeklet-top-ram-processes/">Geeklet: Top RAM Processes</a></p>]]></description>
			<content:encoded><![CDATA[<p><img src="http://cdn2.brettterpstra.com/wp-content/uploads/2011/11/top_ram_processes_screenshot.jpg?9d7bd4" alt="Top RAM Processes screenshot" /></p>

<p>This next geeklet is quite similar to the <a href="http://brettterpstra.com/geeklet-top-cpu-processes/">Top CPU Processes</a> geeklet I last shared. It finds the apps and processes with the biggest memory footprint on your system and lists the top 10. The output looks like:</p>

<pre><code>Top RAM processes

WebProcess       926.62M
Mail             360.05M
Safari           211.48M
iTunes           206.38M
Finder           180.80M
Skype            143.15M
WindowServer     137.12M
LaunchBar        135.71M
mds              118.14M
Reeder           117.47M
</code></pre>

<p>It includes system-level processes, too, so you can see if something other than your running apps is taking up RAM. Keep in mind that RAM is meant to be used, and having it filled up only starts to slow down your system when it has to page it out constantly. That being said, if your system is slowing down, this overview can give you a quick idea what’s happening.<span id="more-3070"></span>Here’s the full code. Copy and paste it into a file called memmeter.rb, save it and run <code>chmod a+x /path/to/memmeter.rb</code>. Then set up your shell geeklet to run <code>/path/to/memmeter.rb</code> and you should be good to go.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby"><span class="co1">#!/usr/bin/ruby</span>
&nbsp;
<span class="kw1">def</span> bytesToMeg<span class="br0">&#40;</span>bytes<span class="br0">&#41;</span>
	<span class="kw1">if</span> bytes.<span class="me1">to_i</span> <span class="sy0">&gt;</span> <span class="br0">&#40;</span><span class="nu0">1024</span><span class="sy0">*</span><span class="nu0">1024</span><span class="br0">&#41;</span>
		bytes = <span class="br0">&#40;</span>bytes.<span class="me1">to_f</span><span class="sy0">/</span><span class="nu0">1048576</span><span class="br0">&#41;</span>
		bytes = <span class="br0">&#40;</span>bytes <span class="sy0">*</span> <span class="nu0">10</span><span class="sy0">**</span><span class="nu0">2</span><span class="br0">&#41;</span>.<span class="me1">round</span>.<span class="me1">to_f</span> <span class="sy0">/</span> <span class="nu0">10</span><span class="sy0">**</span><span class="nu0">2</span>
		bytes = bytes.<span class="me1">to_s</span> <span class="sy0">+</span> <span class="st0">'0'</span> <span class="kw1">if</span> bytes.<span class="me1">to_s</span> =~ <span class="sy0">/</span>\d<span class="sy0">+</span>\.\d$<span class="sy0">/</span>
		<span class="st0">'  '</span> <span class="sy0">+</span> bytes.<span class="me1">to_s</span> <span class="sy0">+</span> <span class="st0">'G'</span>
	<span class="kw1">else</span>
		bytes = <span class="br0">&#40;</span>bytes.<span class="me1">to_f</span><span class="sy0">/</span><span class="nu0">1024</span><span class="br0">&#41;</span>
		bytes = <span class="br0">&#40;</span>bytes <span class="sy0">*</span> <span class="nu0">10</span><span class="sy0">**</span><span class="nu0">2</span><span class="br0">&#41;</span>.<span class="me1">round</span>.<span class="me1">to_f</span> <span class="sy0">/</span> <span class="nu0">10</span><span class="sy0">**</span><span class="nu0">2</span>
		bytes = bytes.<span class="me1">to_s</span> <span class="sy0">+</span> <span class="st0">'0'</span> <span class="kw1">if</span> bytes.<span class="me1">to_s</span> =~ <span class="sy0">/</span>\d<span class="sy0">+</span>\.\d$<span class="sy0">/</span>
		bytes = <span class="st0">' '</span> <span class="sy0">+</span> bytes.<span class="me1">to_s</span> <span class="kw1">if</span> bytes.<span class="me1">to_s</span>.<span class="me1">length</span> == <span class="nu0">5</span>
		bytes.<span class="me1">to_s</span> <span class="sy0">+</span> <span class="st0">'M'</span>
	<span class="kw1">end</span>
<span class="kw1">end</span>
&nbsp;
<span class="kw1">def</span> spacer<span class="br0">&#40;</span><span class="kw3">string</span><span class="br0">&#41;</span>
	<span class="kw1">if</span> <span class="kw3">string</span>.<span class="me1">length</span> <span class="sy0">&gt;</span> <span class="nu0">15</span>
		<span class="kw3">string</span> = <span class="kw3">string</span><span class="br0">&#91;</span><span class="nu0">0</span> .. <span class="nu0">12</span><span class="br0">&#93;</span> <span class="sy0">+</span> <span class="st0">&quot;…  &quot;</span>
	<span class="kw1">else</span>
		spaces = <span class="nu0">16</span> <span class="sy0">-</span> <span class="kw3">string</span>.<span class="me1">length</span>
		<span class="nu0">0</span>.<span class="me1">upto</span><span class="br0">&#40;</span>spaces<span class="br0">&#41;</span> <span class="kw1">do</span>
			<span class="kw3">string</span> <span class="sy0">+</span>= <span class="st0">&quot; &quot;</span>
		<span class="kw1">end</span>
	<span class="kw1">end</span>
	<span class="kw3">string</span>
<span class="kw1">end</span>
&nbsp;
input = <span class="sy0">%</span>x<span class="br0">&#123;</span>ps <span class="sy0">-</span>arcwwwxo <span class="st0">&quot;command rss&quot;</span> <span class="sy0">-</span>m<span class="br0">&#125;</span>
counter = <span class="nu0">0</span>
total = <span class="nu0">0</span>
&nbsp;
title = ARGV<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;-t&quot;</span> ? ARGV<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> : <span class="st0">&quot;Top RAM processes&quot;</span>
<span class="kw3">print</span> <span class="st0">&quot;#{title}<span class="es0">\n</span><span class="es0">\n</span>&quot;</span> <span class="kw1">unless</span> ARGV<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;-t&quot;</span> <span class="sy0">&amp;&amp;</span> ARGV<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>.<span class="kw2">nil</span>?
&nbsp;
input.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>line<span class="sy0">|</span>
	<span class="kw1">if</span> line =~ <span class="sy0">/</span>^<span class="br0">&#40;</span>.<span class="sy0">*</span>?<span class="br0">&#41;</span>\s<span class="sy0">+</span><span class="br0">&#40;</span>\d<span class="br0">&#123;</span><span class="nu0">4</span>,<span class="br0">&#125;</span><span class="br0">&#41;</span>$<span class="sy0">/</span>
		<span class="kw3">exit</span> <span class="kw1">if</span> counter == <span class="nu0">5</span> <span class="kw1">or</span> total == <span class="nu0">10</span>
		<span class="kw3">puts</span> <span class="st0">&quot;#{spacer($1)}#{bytesToMeg($2)}&quot;</span>
		<span class="kw1">if</span> $2.<span class="me1">to_i</span> <span class="sy0">&lt;</span> <span class="nu0">1</span>
			counter <span class="sy0">+</span>= <span class="nu0">1</span>
		<span class="kw1">end</span>
		total <span class="sy0">+</span>= <span class="nu0">1</span>
	<span class="kw1">end</span>
<span class="br0">&#125;</span></pre></div></div>


<p>Just like the Top CPU Processes script, you can call it with <code>memmeter.rb -t "Title to display"</code>, or just <code>-t</code> to display no title. If no parameters are given, it will display “Top RAM Processes.”</p>

<p>Next up, either a good system status overview script or some network status geeklets. Whichever my geek muse picks first, I suppose.</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/geeklet-top-cpu-processes/' rel='bookmark' title='Geeklet: Top CPU processes'>Geeklet: Top CPU processes</a></li>
<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/quick-tip-throttling-parallel-batch-processes-in-terminal/' rel='bookmark' title='Quick Tip: throttling parallel batch processes in Terminal'>Quick Tip: throttling parallel batch processes in Terminal</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/geeklet-top-ram-processes/">Geeklet: Top RAM Processes</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/geeklet-top-ram-processes/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>The MindMeister Markdown Showdown</title>
		<link>http://brettterpstra.com/the-mindmeister-markdown-showdown/</link>
		<comments>http://brettterpstra.com/the-mindmeister-markdown-showdown/#comments</comments>
		<pubDate>Tue, 08 Nov 2011 13:30:27 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[guestblogger]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[mind mapping]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3157</guid>
		<description><![CDATA[<p>Welcome Donald Curtis I’d like to welcome Donald Curtis as a guest blogger today, here to talk about a very cool script we worked on to add some Markdown love to MindMeister. It started with a DM from Donald on Twitter with a link to a GitHub gist, and after some back and forth it became a very cool (and&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/the-mindmeister-markdown-showdown/">The MindMeister Markdown Showdown</a></p>]]></description>
			<content:encoded><![CDATA[<h2>Welcome Donald Curtis</h2>

<p><em>I’d like to welcome <a href="http://milkbox.net">Donald Curtis</a> as a guest blogger today, here to talk about a very cool script we worked on to add some <a href="http://daringfireball.net/projects/markdown/">Markdown</a> love to <a href="http://www.mindmeister.com/">MindMeister</a>. It started with a DM from <a href="http://twitter.com/milkypostman">Donald on Twitter</a> with a link to a GitHub gist, and after some back and forth it became a very cool (and useful) tool. Cool enough that I really wanted to share it here. Since the script is his brainchild and almost entirely his handiwork, I thought it would be cool if Donald did the honors.</em></p>

<h3>The backstory</h3>

<p>I am nearing the end of my first semester as a professor at a small liberal arts college.  My graduate school years left me fairly detached from some of the topics I learned in my undergrad years and so I spend a decent amount of time simply re-aquainting myself with material.  It is easy to digest the second time around, but as I process the material I also have to think about how and what to present.</p>

<p>Mind maps have turned out to be an exceptionally useful tool for organizing the key ideas I want to cover.  And for whatever style of teaching I employ, they end up being a great in-class reference.</p>

<p>When I first started toying with the idea of incorporating mind maps, I did the search for the <em>right</em> software tool. I considered software-only solutions such as <a href="http://itunes.apple.com/us/app/ithoughtshd-mindmapping/id369020033?mt=8">iThoughts HD</a> for iOS and <a href="http://www.mythoughtsformac.com/">My Thoughts</a> for Mac, with <a href="http://db.tt/SmevY5nN">Dropbox</a> as the glue. Both of these apps <em>look</em> amazing and sometimes that’s all the motivation you need.</p>

<p><img style=' float: right; padding: 4px; margin: 0 0 2px 7px;'  src="http://cdn2.brettterpstra.com/wp-content/uploads/2011/11/06_historyview_v4.jpg?9d7bd4" alt="" title="06_historyview_v4" width="300" height="251" class="alignright size-full wp-image-3158" />After reading <a href="http://brettterpstra.com/the-mac-and-ios-mind-mapping-app-extravaganza/">Brett’s Appstravaganza</a> I gave <a href="http://www.mindmeister.com/">MindMeister</a> a spin (because they offer a <em><a href="http://en.wikipedia.org/wiki/Gratis_versus_libre#.22Free_beer.22_vs_.22free_speech.22_distinction">free as in beer</a></em> account). By the time I started paying for the account, I was in. You can read more about the app in Brett’s discussion about mind mapping, but in summary: free trial, web-based (read: multi-platform), decent iOS app, looks good, and roughly equivalent yearly cost to software-only solutions. The added bonus for my application is–on the occasion I have an external link to a picture or movie–MindMeister works on the lecture machines.</p>

<p>Stepping back, I assume teaching isn’t a scenario that a lot of the readership can associate with. Not to worry, mind maps are useful in a wide variety of scenarios.</p>

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

<h3>The MindMeister Markdown Showdown</h3>

<p>MindMeister lacks one feature to satisfy the <a href="http://daringfireball.net/projects/markdown/">Markdown</a> users among us: <em>export to Markdown</em>. <a href="http://brettterpstra.com/quick-tip-mindmanager-to-clean-html/">Brett recently</a> had a <a href="http://brettterpstra.com/tag/quicktip/">Quick Tip</a> that showed how to use <a href="http://www.mindjet.com/">Mindjet MindManager</a> to get a MindMeister map to HTML through <a href="http://daringfireball.net/projects/markdown/">Markdown</a>. I don’t use Mindjet and I didn’t want to really have to install another piece of software and figure out how to migrate my maps through it. After all, the approach was described as a “quick hack” so I assume if I went ahead and described it as a bit contrived–in order to make myself sound smarter–there would be no hard feelings <em>[Ed: there would not]</em>. I would never say such a thing though. It gets the job done.</p>

<p>In order to have a more elegant solution and teach myself <a href="http://www.ruby-lang.org/en/">Ruby</a>, I wrote up a small script that uses the MindMeister API to pull down maps as a markdown-formatted outline. I named the script for clarity as <code>mindmeister2md.rb</code>. With help from Brett to refine much of the output–clean up newlines, fix escaped characters, add notes, add pictures–the core script that I wrote is now very usable.</p>

<h3>Overview</h3>

<p>The script has two functions,</p>

<ul>
<li>list all your maps </li>
<li>output a map as markdown</li>
</ul>

<p>When run with no arguments, the script prints a menu of maps available for you to select:</p>

<pre><code>   Available MindMeister Maps
   ---
    1: Software                      ( 2011-10-31 04:13:58 ) [ 117882387 ]
    2: Internet Layer Protocols      ( 2011-10-27 18:10:26 ) [ 120233062 ]
    3: Network Layer                 ( 2011-10-27 16:41:09 ) [ 119115816 ]
    4: HTML                          ( 2011-10-24 17:59:28 ) [ 117882606 ]
    5: Newbie                        ( 2011-10-24 03:53:40 ) [ 119564927 ]
    6: Ethernet                      ( 2011-10-24 03:53:00 ) [ 116616227 ]
    7: My First iPad Map             ( 2011-10-21 14:19:07 ) [ 119100256 ]
    8: My First iPhone Map           ( 2011-10-21 14:17:30 ) [ 119262965 ]
    9: Threads                       ( 2011-10-20 15:14:29 ) [ 116945908 ]
   10: Computer Hardware             ( 2011-10-12 19:24:19 ) [ 117875898 ]
   11: ACM Programming Tips          ( 2011-10-11 04:03:21 ) [ 117550509 ]
   12: Interprocess Communication    ( 2011-10-04 02:54:56 ) [ 116511362 ]
   Selection: 
</code></pre>

<p>Optionally you can pass either the name of a map (case insensitive) or the map id (given in square brackets in the menu) as argument(s)<sup id="fnref:args"><a href="#fn:args" rel="footnote">1</a></sup>. Both of these would return the “My First iPad Map”,</p>

<pre><code>   ./mindmeister2md.rb my first ipad map
   ./mindmeister2md.rb 119100256
</code></pre>

<p>By default the script outputs the markdown to the screen. There is an optional command-line argument (<code>-o</code>) which will write the markdown to a file.</p>

<p>For the UNIX geeks: Only the generate markdown is sent to standard output (<code>STDOUT</code>).  For Mac users this means the ability to copy the markdown to the copy buffer:</p>

<pre><code>    ./mindmeister2md.rb my first ipad map | pbcopy
</code></pre>

<h3>Configuration</h3>

<p>There is one downside to using the MindMeister API with a script: <em>each user needs to have a <a href="https://www.mindmeister.com/account/api/">MindMeister api key and secret</a> in order to use the script</em><sup id="fnref:doritos"><a href="#fn:doritos" rel="footnote">2</a></sup>. Rather than edit the source code, the script relies on a configuration file named <code>.mindmeister2md</code> in the home directory. The file will be created automatically the first time you run the script; it will complain to you about you needing to update the configuration and specify an API key and your music being too loud.</p>

<p>The configuration file looks like this:</p>

<pre><code>  --- 
   indent: 4
   list_level: 2
   api_key: 
   secret: 
</code></pre>

<p>You get both <code>api_key</code> and <code>secret</code> from the <a href="https://www.mindmeister.com/account/api/">MindMeister api request page</a>. The other two options you can set are:</p>

<dl>
<dt><code>list_level</code></dt>
<dd>The level in the map where lists should begin. At a <code>list_level</code> of 2, the first two levels of the map tree structure are represented as markdown headings, rather than as lists. A <code>list_level</code> of 0 will mean that the map will be exported as a single giant list.</dd>

<dt><code>indent</code></dt>
<dd>specifies the number of spaces that represent a single indent in the list.</dd>
</dl>

<h3>Command Line Options</h3>

<p>Most of the configuration file can also be changed at run-time using optional command line arguments. There is also an option to simply print the maps without actually printing any of them out as well as output to a file.</p>

<p>Usage: mindmeister2md.rb [options] <map id | map name></p>

<dl>
<dt><code>-l, --list</code></dt>
<dd>List available maps and exit.</dd>

<dt><code>-i, --indent &lt;indent&gt;</code></dt>
<dd>Set number of spaces for each indent level. Like temporarily setting <code>indent</code> in the configuration file.</dd>

<dt><code>-s, --listlevel &lt;list_level&gt;</code></dt>
<dd>Set the level at which lists should start. Like temporarily setting <code>list_level</code> in the configuration file.</dd>

<dt><code>-o, --output FILE</code></dt>
<dd>Write output to FILE.</dd>

<dt><code>-h, --help</code></dt>
<dd>Print command-line argument help.</dd>
</dl>

<p>Thanks to Brett for his major contributions to the script–which actually made it useful–and for letting me send him this writeup. You can find me on <a href="http://twitter.com/milkypostman">Twitter</a>, <a href="https://github.com/milkypostman">Github</a>, and I sometimes post bad prose on <a href="http://milkbox.net">milkbox.net</a>.</p>

<p>Check out <a href="https://github.com/milkypostman/mindmeister2md">mindmeister2md on GitHub</a>, or download below.</p>

<h3>Download</h3>

<div class="download_desc"><p class="download-icon"><a href="http://brettterpstra.com/downloads/mm2md" title="Download mindmeister2md (141)"><img src="http://cdn2.brettterpstra.com/wp-content/uploads/downloads/thumbnails/2011/11/mindmeister2mdlogo.png?9d7bd4" alt="download image for mindmeister2md" width="64" /></a><br /><a href="http://brettterpstra.com/downloads/mm2md" title="Download mindmeister2md (141)" class="download-button">Download</a></p><p class="desc"><a href="http://brettterpstra.com/downloads/mm2md" title="Download mindmeister2md (141)">mindmeister2md</a> — A Ruby script by Donald Curtis (and Brett Terpstra) to turn MindMeister mind maps into Markdown outlines, complete with notes and images. <a href="http://brettterpstra.com/?p=3157">More Info</a></p></div>

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

<li id="fn:args">
<p>Normal arguments parsing is abused a bit as you don’t need to quote the entire map name (<code>my first ipad map</code> is actually passing 4 arguments which are concatenated together). <a href="#fnref:args" rev="footnote">↩</a></p>
</li>

<li id="fn:doritos">
<p>Since <code>mindmeister2md.rb</code> is not a compiled program and I cannot–don’t want to–give you <em>my</em> API key, you have to get your own; similar to how I feel anytime I have a bag of Doritos. <a href="#fnref:doritos" rev="footnote">↩</a></p>
</li>

</ol>
</div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/quick-tip-mindmanager-to-clean-html/' rel='bookmark' title='Quick Tip: MindManager to (clean) HTML'>Quick Tip: MindManager to (clean) HTML</a></li>
<li><a href='http://brettterpstra.com/when-plain-text-is-wrong/' rel='bookmark' title='When plain text is wrong'>When plain text is wrong</a></li>
<li><a href='http://brettterpstra.com/the-mac-and-ios-mind-mapping-app-extravaganza/' rel='bookmark' title='The Mac and iOS mind mapping app extravaganza'>The Mac and iOS mind mapping app extravaganza</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/the-mindmeister-markdown-showdown/">The MindMeister Markdown Showdown</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/the-mindmeister-markdown-showdown/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scatterbrains 2: The geekening</title>
		<link>http://brettterpstra.com/scatterbrains-2-the-geekening/</link>
		<comments>http://brettterpstra.com/scatterbrains-2-the-geekening/#comments</comments>
		<pubDate>Sat, 05 Nov 2011 14:00:52 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[productivity]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3078</guid>
		<description><![CDATA[<p>If you read A solution for scatterbrains yesterday, but were left feeling like the solution just wasn’t geeky enough… here’s a Saturday morning post to help you out. You do actually need to read that for this to make any sense. Here, I’ll link it again for you. Geek it up To make this a little geekier: if you’re doing&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/scatterbrains-2-the-geekening/">Scatterbrains 2: The geekening</a></p>]]></description>
			<content:encoded><![CDATA[<p>If you read <a href="http://brettterpstra.com/a-solution-for-scatterbrains/">A solution for scatterbrains</a> yesterday, but were left feeling like the solution just wasn’t <em>geeky</em> enough… here’s a Saturday morning post to help you out. You do actually need to read that for this to make any sense. Here, I’ll <a href="http://brettterpstra.com/a-solution-for-scatterbrains/">link it again</a> for you.</p>

<h3>Geek it up</h3>

<p>To make this a little geekier: if you’re doing this in nvALT, you can right click the note in the list to copy a URL. Then create a <code>wwid</code> (what was I doing) alias in your <code>.bash_profile</code>:</p>

<pre><code>alias wwid='open nvalt://find/YourNoteURL'
</code></pre>

<p>Now you can access that note directly in nvALT from the Terminal with <code>wwid</code>. You can also put that bookmark on a hotkey using any of the various keyboard shortcut apps. Alternatively, if you’re using a plain text file without nvALT, just create an alias or AppleScript to open it in your favorite editor…</p>

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

<h3>No, seriously. Geek it up.</h3>

<p>Given my love for the command line, it’s unsurprising that I wrote a little script to work with this system. You can, of course, get the full contents of the note with <a href="https://github.com/ttscoff/QuickQuestion">QuickQuestion</a> (<code>qq doing</code>). Because I added a “later” section and wanted to clean up the output, I created a second method. My input file (?? What was I doing.md) looks like this:</p>

<pre><code>@(whatiwasdoing)
Currently:
    - 2011-11-03 20:22 | something entirely different
    - 2011-11-03 20:19 | something I've been working on for a while now
Later:
    - stuff I intend to come back to and am not ready to delete yet
    - this part of the file is ignored by the `doing` script
</code></pre>

<p>You can leave that line blank or add your own tag, but there needs to be a line before the “Currently” project starts (the script inserts all new entries at the third line, so it would get weird if that wasn’t the first line of the section, right?). The script also expects the entries to be tabbed in and the project headings to be flush left. The Later section can have any name, or not be there at all. It’s ignored by this script.</p>

<p>Here’s the script<sup id="fnref:bash"><a href="#fn:bash" rel="footnote">1</a></sup> with no comments and no explanation<sup id="fnref:exp"><a href="#fn:exp" rel="footnote">2</a></sup>:</p>


<div class="wp_syntax"><div class="code"><pre class="bash"><span class="re2">DOINGFILE</span>=<span class="st0">&quot;/Users/ttscoff/Dropbox/Notes/nvALT2.1/?? What was I doing.md&quot;</span>
&nbsp;
<span class="kw1">if</span> <span class="br0">&#91;</span><span class="br0">&#91;</span> <span class="re4">$#</span> <span class="re5">-eq</span> <span class="nu0">0</span> <span class="br0">&#93;</span><span class="br0">&#93;</span>; <span class="kw1">then</span>
  <span class="kw2">awk</span> <span class="st_h">'{\
  if (currently==1)
    if (match($0,/^[^\t]/))
      currently=0
    else {
      if ($0 !~ /@done/) {
        sub(/^[ \t]+/,&quot;&quot;)
        print
      }
    }
  else
    if (match($0,&quot;Currently:&quot;))
      currently=1
  }'</span> <span class="st0">&quot;<span class="es2">$DOINGFILE</span>&quot;</span>
<span class="kw1">else</span>
  <span class="re2">input</span>=<span class="st0">&quot;$@&quot;</span>
  <span class="re2">head</span>=<span class="sy0">`</span><span class="kw2">awk</span> <span class="st_h">'NR &lt; 3'</span> <span class="st0">&quot;<span class="es2">$DOINGFILE</span>&quot;</span><span class="sy0">`</span>
  <span class="re2">tail</span>=<span class="sy0">`</span><span class="kw2">awk</span> <span class="st_h">'NR &gt; 2'</span> <span class="st0">&quot;<span class="es2">$DOINGFILE</span>&quot;</span><span class="sy0">`</span>
  <span class="re2">datestamp</span>=<span class="sy0">`</span><span class="kw2">date</span> +<span class="st_h">'%Y-%m-%d %H:%M'</span><span class="sy0">`</span>
  <span class="kw3">echo</span> <span class="re5">-e</span> <span class="st0">&quot;<span class="es2">$head</span><span class="es1">\n</span><span class="es1">\t</span>- <span class="es2">$datestamp</span> | <span class="es2">$input</span><span class="es1">\n</span><span class="es2">$tail</span>&quot;</span> <span class="sy0">&gt;</span> <span class="st0">&quot;<span class="es2">$DOINGFILE</span>&quot;</span>
<span class="kw1">fi</span></pre></div></div>


<p>Just paste this into a file and save it in your path as “doing”. Set the <code>DOINGFILE</code> variable to the path to your note. Lastly, run <code>chmod a+x /path/to/doing</code> to make it executable.</p>

<p>If you run the script with no arguments, it will spit out the “Currently:” section of the file (requires that there be a “Currently:” section of the file). I’d get this from the input file above:</p>

<pre><code>$ doing
- 2011-11-03 20:22 | something entirely different
- 2011-11-03 20:19 | something I've been working on for a while now
$
</code></pre>

<p>If you run it with an argument, it takes it as a new entry, adds a timestamp and inserts it at the top of the Currently section.</p>

<pre><code>$ doing "something I've always wanted to do"
$ doing
- 2011-11-03 20:35 | Something I've always wanted to do
- 2011-11-03 20:22 | something entirely different
- 2011-11-03 20:19 | something I've been working on for a while now
$
</code></pre>

<p>You have to manually edit the file to remove old entries or mark things completed, but the script is a handy means of input. You can interface it with LaunchBar fairly easily, too, if that fits your workflow better. Once you’ve set up the <code>doing</code> script, just create an AppleScript at <code>~/Library/Application Support/LaunchBar/Actions/Doing.scpt</code> and paste this into it:</p>


<div class="wp_syntax"><div class="code"><pre class="applescript"><span class="co1">-- Right click and Copy URL in NV or nvALT to get this</span>
<span class="kw3">property</span> notelink : <span class="st0">&quot;nv://find/%3F%3F%20What%20was%20I%20doing/?NV=Hd9WpOVTTtuY3Zu6gljYVA%3D%3D&quot;</span>
&nbsp;
<span class="kw3">on</span> handle_string<span class="br0">&#40;</span>message<span class="br0">&#41;</span>
  <span class="co1">-- get the input from LaunchBar</span>
  <span class="kw3">if</span> message <span class="kw3">is</span> <span class="st0">&quot;?&quot;</span> <span class="kw3">then</span>
    <span class="co1">-- if the input is just &quot;?&quot; display the script response</span>
    <span class="kw3">set</span> _doing <span class="kw3">to</span> <span class="kw1">do shell script</span> <span class="st0">&quot;/Users/ttscoff/scripts/doing&quot;</span>
    <span class="kw3">tell</span> <span class="kw1">application</span> <span class="st0">&quot;LaunchBar&quot;</span> <span class="kw3">to</span> display <span class="kw3">in</span> large type _doing
  <span class="kw3">else</span> <span class="kw3">if</span> message <span class="kw3">is</span> <span class="st0">&quot;e&quot;</span> <span class="kw2">or</span> message <span class="kw3">is</span> <span class="st0">&quot;edit&quot;</span> <span class="kw3">then</span>
    <span class="co1">-- if the input is just &quot;e&quot; or &quot;edit&quot;, open the nvALT note link</span>
    <span class="co1">-- if you're not using nvALT, replace this with a command to open </span>
    <span class="co1">-- your note in your preferred editor</span>
    <span class="kw1">open</span> location notelink
  <span class="kw3">else</span>
    <span class="co1">-- otherwise, create a new entry using the input</span>
    <span class="kw1">do shell script</span> <span class="st0">&quot;/Users/ttscoff/scripts/doing <span class="es0">\&quot;</span>&quot;</span> <span class="sy0">&amp;</span> message <span class="sy0">&amp;</span> <span class="st0">&quot;<span class="es0">\&quot;</span>&quot;</span>
  <span class="kw3">end</span> <span class="kw3">if</span>
&nbsp;
<span class="kw3">end</span> handle_string</pre></div></div>


<p>In LaunchBar, type ‘doing’ to select the action and hit the spacebar. Type in your entry and hit return. The timestamp will be added by the script, and the netry will be inserted at the third line of your file. If, in the LaunchBar’s text field, you type just a question mark (?), you’ll get a heads-up display of your current entries. Typing just “e” or “edit” will open the link you set up at the top of the script.</p>

<p>There you go. Now you know what I think is keeping me sane and are simultaneously questioning my sanity.</p>

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

<li id="fn:bash">
<p>Yeah, I should have just done it in Ruby (or Perl), but I started out trying to make a Bash one-liner and things just got out of hand. <a href="#fnref:bash" rev="footnote">↩</a></p>
</li>

<li id="fn:exp">
<p><code>man awk</code>. Do it. <a href="#fnref:exp" rev="footnote">↩</a></p>
</li>

</ol>
</div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/an-average-morning/' rel='bookmark' title='An average morning'>An average morning</a></li>
<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/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/scatterbrains-2-the-geekening/">Scatterbrains 2: The geekening</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/scatterbrains-2-the-geekening/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Quick Tip: Quickly clear stuck Growl notifications</title>
		<link>http://brettterpstra.com/quick-tip-quickly-clear-stuck-growl-notifications/</link>
		<comments>http://brettterpstra.com/quick-tip-quickly-clear-stuck-growl-notifications/#comments</comments>
		<pubDate>Fri, 04 Nov 2011 23:00:56 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[growl]]></category>
		<category><![CDATA[launchbar]]></category>
		<category><![CDATA[quicktip]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3111</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. I’ve been having an issue with the latest version of Growl (1.3.1) where notifications randomly get “stuck.” No amount of clicking and option-clicking will make them go away. Until there’s a&#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-quickly-clear-stuck-growl-notifications/">Quick Tip: Quickly clear stuck Growl notifications</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>I’ve been having an issue with the latest version of Growl (1.3.1) where notifications randomly get “stuck.” No amount of clicking and option-clicking will make them go away. Until there’s a fix for this, I’m using a brute force restart to clear them<sup id="fnref:prev"><a href="#fn:prev" rel="footnote">1</a></sup>. I have it set up as an alias (<code>killgrowl</code>) in my <code>.bash_profile</code> and as a LaunchBar action (Restart Growl.scpt). It’s a really simple command:</p>

<pre><code>killall Growl &amp;&amp; open -a Growl
</code></pre>

<p>And in an AppleScript in <code>~/Library/Application Support/LaunchBar/Actions/Relaunch Growl.scpt</code></p>

<pre><code>do shell script "killall Growl &amp;&amp; open -a Growl"
</code></pre>

<p>Easy enough, right? You could run the AppleScript from any launcher (e.g. <a href="http://www.red-sweater.com/fastscripts/">FastScripts</a>), too. Like I said, brute force and lacking in any elegance, but it’ll get me through until a fix comes out.</p>

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

<li id="fn:prev">
<p>This is essentially the same process as my <a href="http://brettterpstra.com/clear-sticky-growl-notifications-with-a-keyboard-shortcut/">previous foray</a>, but that one doesn’t work with the Mac App Store version of Growl. Consider this an update. <a href="#fnref:prev" rev="footnote">↩</a></p>
</li>

</ol>
</div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/clear-sticky-growl-notifications-with-a-keyboard-shortcut/' rel='bookmark' title='Clear sticky Growl notifications with a keyboard shortcut'>Clear sticky Growl notifications with a keyboard shortcut</a></li>
<li><a href='http://brettterpstra.com/nvalt-1-0-5-quick-fixes/' rel='bookmark' title='nvALT 1.0.5 (quick fixes)'>nvALT 1.0.5 (quick fixes)</a></li>
<li><a href='http://brettterpstra.com/quick-tip-applescript-application-toggle/' rel='bookmark' title='Quick tip: AppleScript application toggle'>Quick tip: AppleScript application toggle</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-quickly-clear-stuck-growl-notifications/">Quick Tip: Quickly clear stuck Growl notifications</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/quick-tip-quickly-clear-stuck-growl-notifications/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Word repetition checking with JavaScript</title>
		<link>http://brettterpstra.com/word-repetition-checking-with-javascript/</link>
		<comments>http://brettterpstra.com/word-repetition-checking-with-javascript/#comments</comments>
		<pubDate>Wed, 02 Nov 2011 12:30:47 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[scripting]]></category>
		<category><![CDATA[writing]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=3035</guid>
		<description><![CDATA[<p>Ok, I made something interesting (to me) last night. It’s probably not worth taking the time to write up, but someday someone might find it and think it useful. I apologize for the messiness of the code, if I take this further and clean it up, I’ll update this post. I was working on a few text-analysis features for Marked&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/word-repetition-checking-with-javascript/">Word repetition checking with JavaScript</a></p>]]></description>
			<content:encoded><![CDATA[<p><img style=' display: block; margin-right: auto; margin-left: auto;'  src="http://cdn2.brettterpstra.com/wp-content/uploads/2011/11/Word-Repetition-Screenshot.png?9d7bd4" alt="Word Repetition Screenshot" width="650" height="132" class="aligncenter size-full wp-image-3042" /></p>

<p>Ok, I made something interesting (to me) last night. It’s probably not worth taking the time to write up, but someday someone might find it and think it useful. I apologize for the messiness of the code, if I take this further and clean it up, I’ll update this post.</p>

<p>I was working on a few text-analysis features for <a href="http://markedapp.com">Marked</a> and decided I wanted to be able to show repeated words on a per-paragraph basis. The following is the experiment I did as a proof-of-concept. I decided that I wanted to do this in JavaScript/jQuery for various reasons, so my existing Ruby scripts were mostly useless. Thus, I devised a way to handle it entirely in a WebKit browser.</p>

<h3>Demo</h3>

<p>For the purposes of demonstration, I set up a <a href="http://brettterpstra.com/share/word-repetition-check.php">single-page, dynamic version</a> of this. You can enter any article URL and see the processing take place. Hover over a bolded word to see where it repeats in the paragraph. Note that it’s pulling through a proxy of <a href="http://markdownrules.com/">Marky the Markdownifier</a>, and that some markup will return blanks. Obviously, it also helps to have a lot of text in the article you’re analyzing. Hard up for ideas? <a href="http://brettterpstra.com/share/word-repetition-check.php?url=http://en.wikipedia.org/wiki/Stemming">Try this</a>, or <a href="http://brettterpstra.com/share/word-repetition-check.php?url=http://www.engadget.com/2011/11/02/lenovo-posts-q2-earnings-sees-increase-in-profits-shipments-an/">this</a>. Give it a few seconds to load, it pulls in the content in the background and I haven’t put a progress indicator on it yet.</p>

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

<h3>Breakdown</h3>

<p>I started with a <a href="http://tartarus.org/~martin/PorterStemmer/">Porter Stemmer</a> using a <a href="http://tartarus.org/~martin/PorterStemmer/js.txt">script from tartarus.org</a>. <a href="http://en.wikipedia.org/wiki/Stemming">Stemming</a> allows you to break a word down to a root form, so that all variations of a word can be boiled down and plurals, conjugations and various anomalous representations of a word will all match each other. From there, I do a frequency check to find word roots used more than once within the block being processed, creating an array of the repeated words. Then I re-parse the block, one word at a time, adding some markup to words whose root is found in the previously-created array.</p>

<p>Here’s the main script with a few comments. Until I get this prettied up, I won’t go into a step-by-step. Feel free to lift and improve as you like. Remember to include the <a href="http://tartarus.org/~martin/PorterStemmer/js.txt">porter-stemmer script</a> before this script. Oh, and because I’m lazy, you’ll need to include <a href="http://jquery.com/">jQuery</a> as well. The <code>in_array</code> function is stolen from <a href="http://phpjs.org/functions/in_array:432">php.js</a>.</p>


<div class="wp_syntax"><div class="code"><pre class="javascript"><span class="co1">// from php.js</span>
<span class="kw2">function</span> in_array <span class="br0">&#40;</span>needle<span class="sy0">,</span> haystack<span class="br0">&#41;</span> <span class="br0">&#123;</span>
  <span class="kw1">for</span> <span class="br0">&#40;</span>key <span class="kw1">in</span> haystack<span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span>haystack<span class="br0">&#91;</span>key<span class="br0">&#93;</span> <span class="sy0">==</span> needle<span class="br0">&#41;</span> <span class="br0">&#123;</span>
      <span class="kw1">return</span> <span class="kw2">true</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
  <span class="br0">&#125;</span>
  <span class="kw1">return</span> <span class="kw2">false</span><span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="co1">// short, common words to skip when counting</span>
<span class="kw2">var</span> stopwords <span class="sy0">=</span> <span class="br0">&#91;</span><span class="st0">'1'</span><span class="sy0">,</span><span class="st0">'2'</span><span class="sy0">,</span><span class="st0">'3'</span><span class="sy0">,</span><span class="st0">'4'</span><span class="sy0">,</span><span class="st0">'5'</span><span class="sy0">,</span><span class="st0">'6'</span><span class="sy0">,</span><span class="st0">'7'</span><span class="sy0">,</span><span class="st0">'8'</span><span class="sy0">,</span><span class="st0">'9'</span><span class="sy0">,</span><span class="st0">'0'</span><span class="sy0">,</span><span class="st0">'one'</span><span class="sy0">,</span><span class="st0">'two'</span><span class="sy0">,</span><span class="st0">'three'</span><span class="sy0">,</span><span class="st0">'four'</span><span class="sy0">,</span><span class="st0">'five'</span><span class="sy0">,</span><span class="st0">'about'</span><span class="sy0">,</span><span class="st0">'actually'</span><span class="sy0">,</span><span class="st0">'always'</span><span class="sy0">,</span><span class="st0">'even'</span><span class="sy0">,</span><span class="st0">'given'</span><span class="sy0">,</span><span class="st0">'into'</span><span class="sy0">,</span><span class="st0">'just'</span><span class="sy0">,</span><span class="st0">'not'</span><span class="sy0">,</span><span class="st0">'Im'</span><span class="sy0">,</span><span class="st0">'thats'</span><span class="sy0">,</span><span class="st0">'its'</span><span class="sy0">,</span><span class="st0">'arent'</span><span class="sy0">,</span><span class="st0">'weve'</span><span class="sy0">,</span><span class="st0">'ive'</span><span class="sy0">,</span><span class="st0">'didnt'</span><span class="sy0">,</span><span class="st0">'dont'</span><span class="sy0">,</span><span class="st0">'the'</span><span class="sy0">,</span><span class="st0">'of'</span><span class="sy0">,</span><span class="st0">'to'</span><span class="sy0">,</span><span class="st0">'and'</span><span class="sy0">,</span><span class="st0">'a'</span><span class="sy0">,</span><span class="st0">'in'</span><span class="sy0">,</span><span class="st0">'is'</span><span class="sy0">,</span><span class="st0">'it'</span><span class="sy0">,</span><span class="st0">'you'</span><span class="sy0">,</span><span class="st0">'that'</span><span class="sy0">,</span><span class="st0">'he'</span><span class="sy0">,</span><span class="st0">'was'</span><span class="sy0">,</span><span class="st0">'for'</span><span class="sy0">,</span><span class="st0">'on'</span><span class="sy0">,</span><span class="st0">'are'</span><span class="sy0">,</span><span class="st0">'with'</span><span class="sy0">,</span><span class="st0">'as'</span><span class="sy0">,</span><span class="st0">'I'</span><span class="sy0">,</span><span class="st0">'his'</span><span class="sy0">,</span><span class="st0">'they'</span><span class="sy0">,</span><span class="st0">'be'</span><span class="sy0">,</span><span class="st0">'at'</span><span class="sy0">,</span><span class="st0">'one'</span><span class="sy0">,</span><span class="st0">'have'</span><span class="sy0">,</span><span class="st0">'this'</span><span class="sy0">,</span><span class="st0">'from'</span><span class="sy0">,</span><span class="st0">'or'</span><span class="sy0">,</span><span class="st0">'had'</span><span class="sy0">,</span><span class="st0">'by'</span><span class="sy0">,</span><span class="st0">'hot'</span><span class="sy0">,</span><span class="st0">'but'</span><span class="sy0">,</span><span class="st0">'some'</span><span class="sy0">,</span><span class="st0">'what'</span><span class="sy0">,</span><span class="st0">'there'</span><span class="sy0">,</span><span class="st0">'we'</span><span class="sy0">,</span><span class="st0">'can'</span><span class="sy0">,</span><span class="st0">'out'</span><span class="sy0">,</span><span class="st0">'were'</span><span class="sy0">,</span><span class="st0">'all'</span><span class="sy0">,</span><span class="st0">'your'</span><span class="sy0">,</span><span class="st0">'when'</span><span class="sy0">,</span><span class="st0">'up'</span><span class="sy0">,</span><span class="st0">'use'</span><span class="sy0">,</span><span class="st0">'how'</span><span class="sy0">,</span><span class="st0">'said'</span><span class="sy0">,</span><span class="st0">'an'</span><span class="sy0">,</span><span class="st0">'each'</span><span class="sy0">,</span><span class="st0">'she'</span><span class="sy0">,</span><span class="st0">'which'</span><span class="sy0">,</span><span class="st0">'do'</span><span class="sy0">,</span><span class="st0">'their'</span><span class="sy0">,</span><span class="st0">'if'</span><span class="sy0">,</span><span class="st0">'will'</span><span class="sy0">,</span><span class="st0">'way'</span><span class="sy0">,</span><span class="st0">'many'</span><span class="sy0">,</span><span class="st0">'then'</span><span class="sy0">,</span><span class="st0">'them'</span><span class="sy0">,</span><span class="st0">'would'</span><span class="sy0">,</span><span class="st0">'like'</span><span class="sy0">,</span><span class="st0">'so'</span><span class="sy0">,</span><span class="st0">'these'</span><span class="sy0">,</span><span class="st0">'her'</span><span class="sy0">,</span><span class="st0">'see'</span><span class="sy0">,</span><span class="st0">'him'</span><span class="sy0">,</span><span class="st0">'has'</span><span class="sy0">,</span><span class="st0">'more'</span><span class="sy0">,</span><span class="st0">'could'</span><span class="sy0">,</span><span class="st0">'go'</span><span class="sy0">,</span><span class="st0">'come'</span><span class="sy0">,</span><span class="st0">'did'</span><span class="sy0">,</span><span class="st0">'my'</span><span class="sy0">,</span><span class="st0">'no'</span><span class="sy0">,</span><span class="st0">'get'</span><span class="sy0">,</span><span class="st0">'me'</span><span class="sy0">,</span><span class="st0">'say'</span><span class="sy0">,</span><span class="st0">'too'</span><span class="sy0">,</span><span class="st0">'here'</span><span class="sy0">,</span><span class="st0">'must'</span><span class="sy0">,</span><span class="st0">'such'</span><span class="sy0">,</span><span class="st0">'try'</span><span class="sy0">,</span><span class="st0">'us'</span><span class="sy0">,</span><span class="st0">'own'</span><span class="sy0">,</span><span class="st0">'oh'</span><span class="sy0">,</span><span class="st0">'any'</span><span class="sy0">,</span><span class="st0">'youll'</span><span class="sy0">,</span><span class="st0">'youre'</span><span class="sy0">,</span><span class="st0">'also'</span><span class="sy0">,</span><span class="st0">'than'</span><span class="sy0">,</span><span class="st0">'those'</span><span class="sy0">,</span><span class="st0">'though'</span><span class="sy0">,</span><span class="st0">'thing'</span><span class="sy0">,</span><span class="st0">'things'</span><span class="br0">&#93;</span><span class="sy0">;</span>
&nbsp;
<span class="co1">// takes the text of a paragraph element as input</span>
<span class="co1">// returns marked up text with repeated words in 'b' tags with a class matching their &quot;stemmed&quot; root</span>
<span class="kw2">function</span> checkWords<span class="br0">&#40;</span>input<span class="br0">&#41;</span> <span class="br0">&#123;</span>
&nbsp;
  <span class="kw2">var</span> words <span class="sy0">=</span> input.<span class="me1">split</span><span class="br0">&#40;</span><span class="st0">' '</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="kw2">var</span> wordcount <span class="sy0">=</span> <span class="br0">&#123;</span><span class="br0">&#125;</span><span class="sy0">;</span>
&nbsp;
  <span class="co1">// build an object to count word frequency</span>
  $.<span class="me1">each</span><span class="br0">&#40;</span>words<span class="sy0">,</span><span class="kw2">function</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span><span class="br0">&#123;</span>
    thisWord <span class="sy0">=</span> String<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="co2">/[\/\\]/</span><span class="sy0">,</span><span class="st0">' '</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="co2">/’/g</span><span class="sy0">,</span><span class="st0">&quot;'&quot;</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="co2">/[^a-z' ]/gi</span><span class="sy0">,</span><span class="st0">''</span><span class="br0">&#41;</span>.<span class="me1">toLowerCase</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span><span class="sy0">!</span>in_array<span class="br0">&#40;</span>thisWord<span class="sy0">,</span>stopwords<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
      <span class="kw2">var</span> word <span class="sy0">=</span> stemmer<span class="br0">&#40;</span>thisWord<span class="br0">&#41;</span><span class="sy0">;</span>
      <span class="kw1">if</span> <span class="br0">&#40;</span>wordcount<span class="br0">&#91;</span>word<span class="br0">&#93;</span> <span class="sy0">&gt;</span> <span class="nu0">0</span> <span class="sy0">&amp;&amp;</span> word.<span class="me1">length</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
        wordcount<span class="br0">&#91;</span>word<span class="br0">&#93;</span> <span class="sy0">+=</span> <span class="nu0">1</span><span class="sy0">;</span>
      <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
        wordcount<span class="br0">&#91;</span>word<span class="br0">&#93;</span> <span class="sy0">=</span> <span class="nu0">1</span><span class="sy0">;</span>
      <span class="br0">&#125;</span>
    <span class="br0">&#125;</span>
  <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
  <span class="co1">// convert the object to an object array</span>
  <span class="co1">// include only words repeated more than once within the paragraph</span>
  <span class="kw2">var</span> topwords <span class="sy0">=</span> <span class="kw2">new</span> Array<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  $.<span class="me1">each</span><span class="br0">&#40;</span>wordcount<span class="sy0">,</span><span class="kw2">function</span><span class="br0">&#40;</span>w<span class="sy0">,</span>i<span class="br0">&#41;</span><span class="br0">&#123;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span>i <span class="sy0">&gt;</span> <span class="nu0">1</span><span class="br0">&#41;</span>
      topwords.<span class="me1">push</span><span class="br0">&#40;</span><span class="br0">&#123;</span><span class="st0">'word'</span><span class="sy0">:</span>w<span class="sy0">,</span><span class="st0">'freq'</span><span class="sy0">:</span>i<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
  <span class="co1">// convert the object array to a flat array</span>
  topwordsArr <span class="sy0">=</span> <span class="kw2">new</span> Array<span class="br0">&#40;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    $.<span class="me1">each</span><span class="br0">&#40;</span>topwords<span class="sy0">,</span><span class="kw2">function</span><span class="br0">&#40;</span>i<span class="br0">&#41;</span> <span class="br0">&#123;</span>
    topwordsArr.<span class="me1">push</span><span class="br0">&#40;</span>String<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#91;</span><span class="st0">'word'</span><span class="br0">&#93;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
&nbsp;
  <span class="co1">// re-parse the output, marking up repeated words based on their stems</span>
  <span class="kw2">var</span> output <span class="sy0">=</span> <span class="st0">''</span><span class="sy0">;</span>
  $.<span class="me1">each</span><span class="br0">&#40;</span>words<span class="sy0">,</span><span class="kw2">function</span><span class="br0">&#40;</span>w<span class="br0">&#41;</span> <span class="br0">&#123;</span>
    <span class="kw2">var</span> aWord <span class="sy0">=</span> String<span class="br0">&#40;</span><span class="kw1">this</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw2">var</span> stripWord <span class="sy0">=</span> stemmer<span class="br0">&#40;</span>aWord.<span class="me1">replace</span><span class="br0">&#40;</span><span class="co2">/[\/\\]/</span><span class="sy0">,</span><span class="st0">' '</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="co2">/’/g</span><span class="sy0">,</span><span class="st0">&quot;'&quot;</span><span class="br0">&#41;</span>.<span class="me1">replace</span><span class="br0">&#40;</span><span class="co2">/[^a-z' ]/gi</span><span class="sy0">,</span><span class="st0">''</span><span class="br0">&#41;</span>.<span class="me1">toLowerCase</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span>in_array<span class="br0">&#40;</span>stripWord<span class="sy0">,</span>topwordsArr<span class="br0">&#41;</span><span class="br0">&#41;</span>
      output <span class="sy0">+=</span> <span class="st0">' &lt;b class=&quot;'</span><span class="sy0">+</span>stripWord<span class="sy0">+</span><span class="st0">'&quot;&gt;'</span><span class="sy0">+</span>aWord<span class="sy0">+</span><span class="st0">'&lt;/b&gt;'</span><span class="sy0">;</span>
    <span class="kw1">else</span>
      output <span class="sy0">+=</span> <span class="st0">' '</span><span class="sy0">+</span>aWord<span class="sy0">;</span>
  <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="kw1">return</span> output<span class="sy0">;</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span>$<span class="br0">&#41;</span><span class="br0">&#123;</span>
  <span class="co1">// grab common top-level elements</span>
  grafs <span class="sy0">=</span> $<span class="br0">&#40;</span><span class="st0">'p,ul,ol,blockquote,h1,h2,h3,h4,h5,h6,pre code'</span><span class="sy0">,</span>$<span class="br0">&#40;</span><span class="st0">'#content'</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="co1">// navigate each element found</span>
  $.<span class="me1">each</span><span class="br0">&#40;</span>grafs<span class="sy0">,</span><span class="kw2">function</span><span class="br0">&#40;</span>a<span class="sy0">,</span>g<span class="br0">&#41;</span><span class="br0">&#123;</span>
    <span class="co1">// if it's a paragraph, we'll process it</span>
    <span class="kw1">if</span> <span class="br0">&#40;</span>grafs<span class="br0">&#91;</span>a<span class="br0">&#93;</span>.<span class="me1">tagName</span> <span class="sy0">==</span> <span class="st0">&quot;P&quot;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span>
      $<span class="br0">&#40;</span><span class="st0">'#work'</span><span class="br0">&#41;</span>.<span class="me1">append</span><span class="br0">&#40;</span>$<span class="br0">&#40;</span><span class="st0">'&lt;p&gt;'</span><span class="br0">&#41;</span>.<span class="me1">html</span><span class="br0">&#40;</span>checkWords<span class="br0">&#40;</span>$<span class="br0">&#40;</span>grafs<span class="br0">&#91;</span>a<span class="br0">&#93;</span><span class="br0">&#41;</span>.<span class="me1">text</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="co1">// if not, we just stick it back into the DOM</span>
    <span class="br0">&#125;</span> <span class="kw1">else</span> <span class="br0">&#123;</span>
      $<span class="br0">&#40;</span><span class="st0">'#work'</span><span class="br0">&#41;</span>.<span class="me1">append</span><span class="br0">&#40;</span>grafs<span class="br0">&#91;</span>a<span class="br0">&#93;</span><span class="br0">&#41;</span><span class="sy0">;</span>
    <span class="br0">&#125;</span>
  <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="co1">// set up hover listeners on the 'b' elements</span>
  <span class="co1">// the class is pulled from the hovered element</span>
  <span class="co1">// all similar words are highlighted on hover</span>
  $<span class="br0">&#40;</span><span class="st0">'b'</span><span class="sy0">,</span><span class="st0">'#work'</span><span class="br0">&#41;</span>.<span class="me1">hover</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
    <span class="kw2">var</span> thisClass <span class="sy0">=</span> <span class="kw1">this</span>.<span class="me1">className</span><span class="sy0">;</span>
    $<span class="br0">&#40;</span><span class="st0">'.'</span><span class="sy0">+</span>thisClass<span class="br0">&#41;</span>.<span class="me1">addClass</span><span class="br0">&#40;</span><span class="st0">'highlight'</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span><span class="sy0">,</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#123;</span>
    $<span class="br0">&#40;</span><span class="st0">'.highlight'</span><span class="br0">&#41;</span>.<span class="me1">removeClass</span><span class="br0">&#40;</span><span class="st0">'highlight'</span><span class="br0">&#41;</span><span class="sy0">;</span>
  <span class="br0">&#125;</span><span class="br0">&#41;</span><span class="sy0">;</span>
<span class="br0">&#125;</span><span class="br0">&#41;</span><span class="br0">&#40;</span>jQuery<span class="br0">&#41;</span><span class="sy0">;</span></pre></div></div>


<p>This little bit of css will add the highlighting and a nice fade in compatible browsers:</p>


<div class="wp_syntax"><div class="code"><pre class="css">b <span class="br0">&#123;</span>
  <span class="kw1">font-weight</span><span class="sy0">:</span><span class="kw2">bold</span><span class="sy0">;</span>
  -webkit-transition<span class="sy0">:</span><span class="kw1">color</span> .2s ease-in-out<span class="sy0">;</span>
  -moz-transition<span class="sy0">:</span><span class="kw1">color</span> .2s ease-in-out<span class="sy0">;</span>
  -o-transition<span class="sy0">:</span><span class="kw1">color</span> .2s ease-in-out<span class="sy0">;</span>
  transition<span class="sy0">:</span><span class="kw1">color</span> .2s ease-in-out<span class="sy0">;</span>
<span class="br0">&#125;</span>
<span class="re1">.highlight</span> <span class="br0">&#123;</span> <span class="kw1">color</span><span class="sy0">:</span>rgba<span class="br0">&#40;</span><span class="nu0">207</span><span class="sy0">,</span> <span class="nu0">95</span><span class="sy0">,</span> <span class="nu0">205</span><span class="sy0">,</span> <span class="nu0">1</span><span class="br0">&#41;</span><span class="sy0">;</span><span class="br0">&#125;</span></pre></div></div>


<p>If I decide to include this in Marked, it will definitely get some revamping. Like I said… proof-of-concept. Check out the demo, though, it’s kind of neat.</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/a-simple-but-handy-bash-function-console/' rel='bookmark' title='A simple but handy Bash function: console'>A simple but handy Bash function: console</a></li>
<li><a href='http://brettterpstra.com/ampersands-javascript/' rel='bookmark' title='Ampersands &amp; Javascript'>Ampersands &amp; Javascript</a></li>
<li><a href='http://brettterpstra.com/quick-tip-this-command-line-trick-is-tops/' rel='bookmark' title='Quick Tip: This command line trick is tops'>Quick Tip: This command line trick is tops</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/word-repetition-checking-with-javascript/">Word repetition checking with JavaScript</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/word-repetition-checking-with-javascript/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Bash auto-complete for running applications</title>
		<link>http://brettterpstra.com/bash-auto-complete-for-running-applications/</link>
		<comments>http://brettterpstra.com/bash-auto-complete-for-running-applications/#comments</comments>
		<pubDate>Tue, 04 Oct 2011 22:58:19 +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[scripting]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=2921</guid>
		<description><![CDATA[<p>I’m not up for doing a full Bash autocomplete tutorial tonight, but wanted to share something I figured out instead of eating lunch. Here it is with a modicum of explanation. I’ve been using Jon Stovell’s quit script to stop running applications with various save options as part of tweaking a safer universal computing setup with Dropbox. For various reasons&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/bash-auto-complete-for-running-applications/">Bash auto-complete for running applications</a></p>]]></description>
			<content:encoded><![CDATA[<p>I’m not up for doing a full Bash autocomplete tutorial tonight, but wanted to share something I figured out instead of eating lunch. Here it is with a modicum of explanation.</p>

<p>I’ve been using Jon Stovell’s <a href="http://web.me.com/jonstovell/personal/Software.html">quit script</a> to stop running applications with various save options as part of tweaking a safer <a href="http://brettterpstra.com/dropbox-and-seamless-mutli-mac-computing/">universal computing setup with Dropbox</a>. For various reasons I found myself wanting to autocomplete application names, but only ones that were currently running. This technique could be used for any command line tool that runs on running, windowed applications. This version doesn’t do anything for faceless processes, but I’ll show you that in a minute.</p>

<p>A short version to start with. You can run a long one-liner in .bash_profile to return an array of running apps using <code>osascript</code> (AppleScript) and pass it to <code>complete</code> with the <code>-W</code> parameter to accept the variable instead of a function:</p>

<pre><code>APP_COMPLETE=( $( echo "$(osascript -e "set AppleScript's text item delimiters to \"\n\"" -e "tell application \"System Events\" to return (displayed name of every application process whose (background only is false and displayed name is not \"Finder\")) as text" 2&gt;/dev/null)"|sed -e 's/ /\\ /g' ) )

complete -o default -W "${APP_COMPLETE[*]}" quit
</code></pre>

<p>This works but isn’t case insensitive, and I’m never satisfied until things are as lazy as possible.</p>

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

<h3>Case-insensitive completion of running app names</h3>

<p>The script below is in <code>~/.app_completions</code> along with my app name completion script for launching (as mentioned in the <a href="http://brettterpstra.com/grabbing-a-mac-apps-icon-advanced-bash-usage-2/">Bash version of my Get an App’s Icon series</a>). You could just as easily add it to your <code>.bash_profile</code>, but it’s easier for me to keep track of if it’s external.</p>

<p>In <code>.app_completions</code> is this function and <code>complete</code> command:</p>


<div class="wp_syntax"><div class="code"><pre class="bash">_complete_running_apps <span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
  <span class="kw3">local</span> cur prev 
  <span class="kw3">local</span> <span class="re2">LC_ALL</span>=<span class="st_h">'C'</span>
&nbsp;
  <span class="re2">COMPREPLY</span>=<span class="br0">&#40;</span><span class="br0">&#41;</span>
  <span class="re2">cur</span>=<span class="co1">${COMP_WORDS[COMP_CWORD]}</span>
  <span class="re2">prev</span>=<span class="co1">${COMP_WORDS[COMP_CWORD-1]}</span>
&nbsp;
  <span class="co0"># do not attempt completion if we're specifying an option</span>
  <span class="br0">&#91;</span><span class="br0">&#91;</span> <span class="st0">&quot;<span class="es2">$cur</span>&quot;</span> == -<span class="sy0">*</span> <span class="br0">&#93;</span><span class="br0">&#93;</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">return</span> <span class="nu0">0</span>
&nbsp;
  <span class="co0"># Escape dots in paths for grep </span>
  <span class="re2">cur</span>=<span class="co1">${cur//\./\\\.}</span>
&nbsp;
  <span class="kw3">local</span> <span class="re2">IFS</span>=<span class="st0">&quot;
&quot;</span>
  <span class="re2">COMPREPLY</span>=<span class="br0">&#40;</span> $<span class="br0">&#40;</span> <span class="kw3">echo</span> <span class="st0">&quot;<span class="es4">$(osascript -e &quot;set AppleScript's text item delimiters to \&quot;\n\&quot;&quot; -e &quot;tell application \&quot;System Events\&quot; to return (displayed name of every application process whose (background only is false and displayed name is not \&quot;Finder\&quot;)</span>) as text&quot;</span> <span class="nu0">2</span><span class="sy0">&gt;/</span>dev<span class="sy0">/</span>null<span class="br0">&#41;</span><span class="st0">&quot;|grep -i &quot;</span>^<span class="re1">$cur</span><span class="st0">&quot; | sed -e 's/ /\\ /g' ) )
&nbsp;
  return 0
}
&nbsp;
complete -o bashdefault -o default -o nospace -F _complete_running_apps quit 2&gt;/dev/null || complete -o default -o nospace -F _complete_running_apps quit</span></pre></div></div>


<p>It starts start by setting up a few variables to read what the completion command provides as partial text and preceding words. Then it runs the same AppleScript<sup id="fnref:ps"><a href="#fn:ps" rel="footnote">1</a></sup> from before, except that by running it through a function we’re taking control of the matching process. Thus, we can use <code>grep -i</code> for case-insensitive matching. We set $COMPREPLY to the result and it’s read in by the auto-complete on the command line.</p>

<p>In the <code>complete</code> command at the end, note that it’s only currently setting up completion for the <code>quit</code> command. Just change <code>quit</code> to something else if you’re using it for something else.</p>

<p>Now, just add a line to <code>.bash_profile</code> to read in the script on login:</p>

<pre><code>source ~/.app_completions
</code></pre>

<h3>Bonus: kill ‘em all.</h3>

<p>You can also do something similar with all running processes, handy for commands like <code>killall</code>. This could also be easily converted to a one-liner like the first script above, but just for the sake of laziness:</p>


<div class="wp_syntax"><div class="code"><pre class="bash">_complete_running_processes <span class="br0">&#40;</span><span class="br0">&#41;</span>
<span class="br0">&#123;</span>
    <span class="kw3">local</span> cur prev 
    <span class="kw3">local</span> <span class="re2">LC_ALL</span>=<span class="st_h">'C'</span>
&nbsp;
    <span class="re2">COMPREPLY</span>=<span class="br0">&#40;</span><span class="br0">&#41;</span>
    <span class="re2">cur</span>=<span class="co1">${COMP_WORDS[COMP_CWORD]}</span>
    <span class="re2">prev</span>=<span class="co1">${COMP_WORDS[COMP_CWORD-1]}</span>
&nbsp;
    <span class="co0"># do not attempt completion if we're specifying an option</span>
    <span class="br0">&#91;</span><span class="br0">&#91;</span> <span class="st0">&quot;<span class="es2">$cur</span>&quot;</span> == -<span class="sy0">*</span> <span class="br0">&#93;</span><span class="br0">&#93;</span> <span class="sy0">&amp;&amp;</span> <span class="kw3">return</span> <span class="nu0">0</span>
&nbsp;
    <span class="co0"># Escape dots in paths for grep</span>
    <span class="re2">cur</span>=<span class="co1">${cur//\./\\\.}</span>
&nbsp;
    <span class="kw3">local</span> <span class="re2">IFS</span>=<span class="st0">&quot;
&quot;</span>
    <span class="re2">COMPREPLY</span>=<span class="br0">&#40;</span> $<span class="br0">&#40;</span><span class="kw2">ps</span> axc<span class="sy0">|</span><span class="kw2">awk</span> <span class="st_h">'{ print $5 }'</span><span class="sy0">|</span><span class="kw2">sort</span> <span class="re5">-u</span><span class="sy0">|</span><span class="kw2">grep</span> <span class="re5">-v</span> <span class="st0">&quot;^[\-\(]&quot;</span><span class="sy0">|</span><span class="kw2">grep</span> <span class="re5">-i</span> <span class="st0">&quot;^<span class="es2">$cur</span>&quot;</span><span class="br0">&#41;</span> <span class="br0">&#41;</span>
&nbsp;
    <span class="kw3">return</span> <span class="nu0">0</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw3">complete</span> <span class="re5">-o</span> bashdefault <span class="re5">-o</span> default <span class="re5">-o</span> nospace <span class="re5">-F</span> _complete_running_processes <span class="kw2">killall</span> <span class="nu0">2</span><span class="sy0">&gt;/</span>dev<span class="sy0">/</span>null <span class="sy0">||</span> <span class="kw3">complete</span> <span class="re5">-o</span> default <span class="re5">-o</span> nospace <span class="re5">-F</span> _complete_running_processes <span class="kw2">killall</span></pre></div></div>


<p>The <code>ps axc</code> reports all running processes with just their executable name. The <code>awk</code> after it grabs the executable names from each line. They’re passed as a list to <code>sort -u</code> which removes duplicates and sorts them in alphabetical order. The first grep removes processes beginning with “(“ or “-” so we can exclude private and terminal commands. There are still plenty of lines autocompleting that you really don’t want to kill, but hey, the command line can be a dangerous place. The last grep does our case-insensitive match for anything that begins with the partial string that we’re completing off of.</p>

<p>So that’s my lunch break. It will ease my hunger pains if someone else finds any use for this. Be sure to let me know!</p>

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

<li id="fn:ps">
<p>There’s probably a way to do this with <code>ps</code> and some string manipulation, but it was lunchtime and I was hungry. <a href="#fnref:ps" rev="footnote">↩</a></p>
</li>

</ol>
</div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/fk-a-useful-bash-function/' rel='bookmark' title='fk: a useful bash function'>fk: a useful bash function</a></li>
<li><a href='http://brettterpstra.com/duplicating-safari-browsing-sessions-between-macs/' rel='bookmark' title='Duplicating Safari browsing sessions between Macs'>Duplicating Safari browsing sessions between Macs</a></li>
<li><a href='http://brettterpstra.com/quick-tip-some-inputrc-fun/' rel='bookmark' title='Quick Tip: some .inputrc fun'>Quick Tip: some .inputrc fun</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/bash-auto-complete-for-running-applications/">Bash auto-complete for running applications</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/bash-auto-complete-for-running-applications/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Automating random giveaways, v1.0</title>
		<link>http://brettterpstra.com/automating-random-giveaways-v1-0/</link>
		<comments>http://brettterpstra.com/automating-random-giveaways-v1-0/#comments</comments>
		<pubDate>Sat, 01 Oct 2011 17:15:13 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[applescript]]></category>
		<category><![CDATA[automation]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=2879</guid>
		<description><![CDATA[<p>To pick the winners for the Yoink and Listary giveaways, I wrote an AppleScript to make the process completely random and as painless as possible for me. I still have plans for making a similar WordPress plugin, but that’s still in the planning stages. For now, this is working quite well and I thought I’d share it. I doubt many&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/automating-random-giveaways-v1-0/">Automating random giveaways, v1.0</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/10/winduprobot.jpg?9d7bd4" alt="windup robot" title="windup robot" width="200" height="334" class="alignright size-full wp-image-2880" />To pick the winners for the Yoink and Listary giveaways, I wrote an AppleScript to make the process completely random and as painless as possible for me. I still have plans for making a similar WordPress plugin, but that’s still in the planning stages. For now, this is working quite well and I thought I’d share it. I doubt many people have the exact same setup and requirements, but the basic structure might be helpful for other projects.</p>

<p>It’s designed to work with promo code giveaways. So far, that’s what my giveaways have been. If I end up running a giveaway with a different registration method, I’ll extend the script and post an update for anyone interested.</p>

<p>This method currently has two requirements/limitations based on my own needs and setup. First, it only works with Mail.app for collecting entries and sending notifications. Second,  the regular expressions it uses to find the entrants name, email and IP address are based on the standard WordPress comment notification emails. The basic idea here could easily be applied to other AppleScript-able email applications and modified to parse any format, but I’ll leave that up to intrepid readers for now.</p>

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

<h3>How it works</h3>

<p>First, I do a search for the subject line in Mail. All of the comment notifications that WordPress sends me for the post have the same subject line, so that gathers them all very quickly. All that matters is that I can select them all before running the script.</p>

<p>Next, I run the AppleScript. It begins by asking me for the giveaway app’s name and requests my list of promo codes. Then the script pulls the names and the message content from each selected email, passing the information to a Ruby script which scans the content for the actual email address (necessary because the actual sender on the email is always my WordPress address) and entrant’s name/handle and IP. The list of results are then passed to a second Ruby script along with the promo codes. This script checks for duplicates in the emails and IPs, picks enough random numbers (range 0 — number of entrants) to match each code provided (recursive function to avoid duplicate numbers). The Ruby script then opens a new message in Mail.app for each winner, and populates it with recipient, subject, congratulatory message (including code) and signature. It also adds the mailto: link with all of this info to an HTML file on the Desktop for reference.</p>

<p>It needs some improvements, especially in the mail creation routine. It currently uses the <code>mailto</code> AppleScript command, but really should create the outgoing message step by step, which would ultimately allow for complete automation at some point. For the time being I still want to be able to confirm the winners and message content anyway; I’ll automate more when I have full trust in it.</p>

<h4>The AppleScript</h4>


<div class="wp_syntax"><div class="code"><pre class="applescript"><span class="coMULTI">(* 
PickWinners by Brett Terpstra, 2011, freely distributed
Picks random winners from selected WordPress comment notification emails in Mail.app
Checks for duplicate emails and IP addresses
On run, requests Application title and a newline-separated list of promo codes
Picks winners from list for each promo code and opens ready-to-send notification emails in Mail.app
Saves list of winners in HTML file with mailto links (including message and promo code)
*)</span>
&nbsp;
<span class="kw3">set</span> pickWinnerScript <span class="kw3">to</span> <span class="br0">&#40;</span><span class="kw1">path to</span> <span class="kw1">me</span><span class="br0">&#41;</span> <span class="sy0">&amp;</span> <span class="st0">&quot;Contents:Resources:Scripts:pickwinners.rb&quot;</span> <span class="kw2">as</span> <span class="kw1">string</span>
<span class="kw3">set</span> extractEmailScript <span class="kw3">to</span> <span class="br0">&#40;</span><span class="kw1">path to</span> <span class="kw1">me</span><span class="br0">&#41;</span> <span class="sy0">&amp;</span> <span class="st0">&quot;Contents:Resources:Scripts:extractemail.rb&quot;</span> <span class="kw2">as</span> <span class="kw1">string</span>
<span class="kw3">property</span> winners : <span class="st0">&quot;&quot;</span>
<span class="kw3">set</span> _res <span class="kw3">to</span> <span class="kw1">display dialog</span> <span class="st0">&quot;Application name?&quot;</span> <span class="kw1">default answer</span> <span class="st0">&quot;&quot;</span>
<span class="kw3">set</span> appname <span class="kw3">to</span> <span class="kw1">text</span> returned <span class="kw3">of</span> _res
<span class="kw3">set</span> _res <span class="kw3">to</span> <span class="kw1">display dialog</span> <span class="st0">&quot;Enter promo codes&quot;</span> <span class="kw1">default answer</span> <span class="st0">&quot;Paste codes, one per line&quot;</span>
<span class="kw3">set</span> codes <span class="kw3">to</span> <span class="kw1">text</span> returned <span class="kw3">of</span> _res
&nbsp;
<span class="kw3">tell</span> <span class="kw1">application</span> <span class="st0">&quot;Mail&quot;</span>
	<span class="kw3">set</span> _sel <span class="kw3">to</span> <span class="kw2">the</span> <span class="kw1">selection</span>
	<span class="kw3">set</span> entries <span class="kw3">to</span> <span class="br0">&#123;</span><span class="br0">&#125;</span>
&nbsp;
	<span class="kw3">repeat</span> <span class="kw3">with</span> _msg <span class="kw3">in</span> _sel
		<span class="kw3">set</span> nameAndEmail <span class="kw3">to</span> <span class="kw1">do shell script</span> <span class="st0">&quot;<span class="es0">\&quot;</span>&quot;</span> <span class="sy0">&amp;</span> <span class="br0">&#40;</span><span class="kw1">POSIX path</span> <span class="kw3">of</span> extractEmailScript<span class="br0">&#41;</span> <span class="sy0">&amp;</span> <span class="st0">&quot;<span class="es0">\&quot;</span> <span class="es0">\&quot;</span>&quot;</span> <span class="sy0">&amp;</span> <span class="kw1">content</span> <span class="kw3">of</span> _msg <span class="sy0">&amp;</span> <span class="st0">&quot;<span class="es0">\&quot;</span>&quot;</span>
		<span class="kw3">set</span> <span class="kw3">end</span> <span class="kw3">of</span> entries <span class="kw3">to</span> nameAndEmail
	<span class="kw3">end</span> <span class="kw3">repeat</span>
&nbsp;
	<span class="kw3">set</span> <span class="br0">&#123;</span>astid, AppleScript<span class="co2">'</span>s <span class="kw1">text</span> <span class="kw1">item</span> <span class="kw1">delimiters</span><span class="br0">&#125;</span> <span class="kw3">to</span> <span class="br0">&#123;</span>AppleScript<span class="co2">'</span>s <span class="kw1">text</span> <span class="kw1">item</span> <span class="kw1">delimiters</span>, <span class="st0">&quot;
&quot;</span><span class="br0">&#125;</span>
	<span class="kw3">set</span> emails <span class="kw3">to</span> entries <span class="kw2">as</span> <span class="kw1">string</span>
	<span class="kw3">set</span> AppleScript<span class="co2">'</span>s <span class="kw1">text</span> <span class="kw1">item</span> <span class="kw1">delimiters</span> <span class="kw3">to</span> astid
&nbsp;
	<span class="kw3">set</span> winners <span class="kw3">to</span> <span class="kw1">do shell script</span> <span class="st0">&quot;<span class="es0">\&quot;</span>&quot;</span> <span class="sy0">&amp;</span> <span class="br0">&#40;</span><span class="kw1">POSIX path</span> <span class="kw3">of</span> pickWinnerScript<span class="br0">&#41;</span> <span class="sy0">&amp;</span> <span class="st0">&quot;<span class="es0">\&quot;</span>  <span class="es0">\&quot;</span>&quot;</span> <span class="sy0">&amp;</span> appname <span class="sy0">&amp;</span> <span class="st0">&quot;<span class="es0">\&quot;</span> <span class="es0">\&quot;</span>&quot;</span> <span class="sy0">&amp;</span> codes <span class="sy0">&amp;</span> <span class="st0">&quot;<span class="es0">\&quot;</span> <span class="es0">\&quot;</span>&quot;</span> <span class="sy0">&amp;</span> emails <span class="sy0">&amp;</span> <span class="st0">&quot;<span class="es0">\&quot;</span>&quot;</span>
<span class="kw3">end</span> <span class="kw3">tell</span>
&nbsp;
<span class="kw3">if</span> winners <span class="kw3">is</span> <span class="st0">&quot;error&quot;</span> <span class="kw3">then</span>
	<span class="kw1">display dialog</span> <span class="st0">&quot;There was an error generating winners&quot;</span>
<span class="kw3">else</span>
	<span class="kw3">set</span> _btn <span class="kw3">to</span> <span class="kw1">display dialog</span> <span class="st0">&quot;Winners written to &quot;</span> <span class="sy0">&amp;</span> winners <span class="kw1">buttons</span> <span class="br0">&#123;</span><span class="st0">&quot;OK&quot;</span>, <span class="st0">&quot;Open in Safari&quot;</span><span class="br0">&#125;</span>
	<span class="kw3">if</span> button returned <span class="kw3">of</span> _btn <span class="kw3">is</span> <span class="st0">&quot;Open in Safari&quot;</span> <span class="kw3">then</span>
		<span class="kw3">tell</span> <span class="kw1">application</span> <span class="st0">&quot;Safari&quot;</span> <span class="kw3">to</span> <span class="kw1">open</span> <span class="br0">&#40;</span><span class="kw1">POSIX file</span> winners<span class="br0">&#41;</span> <span class="kw2">as</span> <span class="kw1">alias</span>
	<span class="kw3">end</span> <span class="kw3">if</span>
<span class="kw3">end</span> <span class="kw3">if</span></pre></div></div>


<h4>extractemail.rb</h4>


<div class="wp_syntax"><div class="code"><pre class="ruby"><span class="co1">#!/usr/bin/env ruby</span>
&nbsp;
input = ARGV.<span class="me1">join</span><span class="br0">&#40;</span><span class="st0">&quot; &quot;</span><span class="br0">&#41;</span>
emailmatch = input.<span class="me1">match</span><span class="br0">&#40;</span><span class="sy0">/</span>E<span class="sy0">-</span>mail : <span class="br0">&#40;</span>.<span class="sy0">*</span><span class="br0">&#41;</span><span class="sy0">/</span><span class="br0">&#41;</span>
namematch = input.<span class="me1">match</span><span class="br0">&#40;</span><span class="sy0">/</span>Author : <span class="br0">&#40;</span>.<span class="sy0">*</span>?<span class="br0">&#41;</span> \<span class="br0">&#40;</span>IP: <span class="br0">&#40;</span>.<span class="sy0">*</span>?<span class="br0">&#41;</span>\<span class="br0">&#41;</span><span class="sy0">/</span><span class="br0">&#41;</span>
&nbsp;
<span class="kw3">print</span> <span class="st0">&quot;#{namematch[1].strip} &lt;#{emailmatch[1].strip}&gt; (#{namematch[2].strip})&quot;</span></pre></div></div>


<h4>pickwinners.rb</h4>


<div class="wp_syntax"><div class="code"><pre class="ruby"><span class="co1">#!/usr/bin/env ruby</span>
<span class="kw3">require</span> <span class="st0">'ftools'</span>
&nbsp;
appname = ARGV<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>
ARGV.<span class="me1">shift</span>
codes = ARGV<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="kw3">split</span>
count = codes.<span class="me1">length</span>
ARGV.<span class="me1">shift</span>
input = ARGV<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>.<span class="me1">uniq</span>
&nbsp;
norepeat_email = <span class="br0">&#91;</span><span class="br0">&#93;</span>
norepeat_IP = <span class="br0">&#91;</span><span class="br0">&#93;</span>
entries = <span class="br0">&#91;</span><span class="br0">&#93;</span>
&nbsp;
input.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>entry<span class="sy0">|</span>
  name,email,ip = entry.<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">&#41;</span> <span class="sy0">*&lt;</span><span class="br0">&#40;</span><span class="br0">&#91;</span>^ <span class="br0">&#93;</span><span class="sy0">+</span><span class="br0">&#41;</span><span class="sy0">&gt;</span> \<span class="br0">&#40;</span><span class="br0">&#40;</span>.<span class="sy0">*</span>?<span class="br0">&#41;</span>\<span class="br0">&#41;</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">unless</span> <span class="br0">&#40;</span>norepeat_email.<span class="kw1">include</span>?<span class="br0">&#40;</span>email<span class="br0">&#41;</span> <span class="sy0">||</span> norepeat_IP.<span class="kw1">include</span>?<span class="br0">&#40;</span>ip<span class="br0">&#41;</span><span class="br0">&#41;</span>
    norepeat_email.<span class="me1">push</span><span class="br0">&#40;</span>email<span class="br0">&#41;</span>
    norepeat_IP.<span class="me1">push</span><span class="br0">&#40;</span>ip<span class="br0">&#41;</span>
    entries <span class="sy0">&lt;&lt;</span> <span class="br0">&#123;</span> <span class="st0">'name'</span> <span class="sy0">=&gt;</span> name, <span class="st0">'email'</span> <span class="sy0">=&gt;</span> email <span class="br0">&#125;</span>
  <span class="kw1">end</span>
<span class="br0">&#125;</span>
&nbsp;
<span class="kw1">def</span> pick_number<span class="br0">&#40;</span>max,numbers<span class="br0">&#41;</span>
  num = <span class="kw3">rand</span><span class="br0">&#40;</span>max<span class="br0">&#41;</span>
  <span class="kw1">if</span> numbers.<span class="kw1">include</span>? num
    pick_number<span class="br0">&#40;</span>max,numbers<span class="br0">&#41;</span>
  <span class="kw1">else</span>
    <span class="kw2">return</span> num
  <span class="kw1">end</span>
<span class="kw1">end</span>
&nbsp;
randoms = <span class="br0">&#91;</span><span class="br0">&#93;</span>
count.<span class="me1">times</span> <span class="kw1">do</span>
  randoms.<span class="me1">push</span><span class="br0">&#40;</span>pick_number<span class="br0">&#40;</span>entries.<span class="me1">length</span>,randoms<span class="br0">&#41;</span><span class="br0">&#41;</span>
<span class="kw1">end</span>
&nbsp;
winners = <span class="br0">&#91;</span><span class="br0">&#93;</span>
randoms.<span class="me1">each_with_index</span> <span class="br0">&#123;</span><span class="sy0">|</span>winner,i<span class="sy0">|</span>
  entry = entries<span class="br0">&#91;</span>winner<span class="br0">&#93;</span>
  name = entry<span class="br0">&#91;</span><span class="st0">'name'</span><span class="br0">&#93;</span>
  email = entry<span class="br0">&#91;</span><span class="st0">'email'</span><span class="br0">&#93;</span>
  mailto = <span class="sy0">%</span>Q<span class="br0">&#123;</span>mailto:<span class="co1">#{email}?subject=Congratulations #{name}, you won!&amp;body=Here is your promo code for #{appname}: #{codes[i]}%0A%0AThanks for reading!%0A%0A-Brett}</span>
  link = <span class="sy0">%</span>Q<span class="br0">&#123;</span><span class="sy0">&lt;</span>li<span class="sy0">&gt;&lt;</span>a href=<span class="st0">&quot;#{mailto}&quot;</span><span class="sy0">&gt;</span><span class="co1">#{name} &lt;#{email}&gt;&lt;/a&gt;&lt;/li&gt;}</span>
  winners.<span class="me1">push</span><span class="br0">&#40;</span>link<span class="br0">&#41;</span>
  <span class="sy0">%</span>x<span class="br0">&#123;</span>echo <span class="st0">'tell application &quot;Mail&quot; to mailto &quot;#{mailto.gsub(/'</span><span class="sy0">/</span>,<span class="st0">&quot;<span class="es0">\'</span>&quot;</span><span class="br0">&#41;</span><span class="br0">&#125;</span><span class="st0">&quot;'|osascript}
}
&nbsp;
if winners.length == count
  output = &quot;</span><span class="sy0">&lt;</span>ul<span class="sy0">&gt;</span><span class="st0">&quot;
  output += winners.join(&quot;</span>\n<span class="st0">&quot;)
  output += &quot;</span><span class="sy0">&lt;/</span>ul<span class="sy0">&gt;</span><span class="st0">&quot;
&nbsp;
  outfile = File.new(File.expand_path(&quot;</span>~<span class="sy0">/</span>Desktop<span class="sy0">/</span><span class="co1">#{appname}Winners.html&quot;),'w+')</span>
  outfile.<span class="kw3">puts</span> output
  outfile.<span class="me1">close</span>
  <span class="kw3">puts</span> <span class="kw4">File</span>.<span class="me1">expand_path</span><span class="br0">&#40;</span><span class="st0">&quot;~/Desktop/#{appname}Winners.html&quot;</span><span class="br0">&#41;</span>
<span class="kw1">else</span>
  <span class="kw3">puts</span> <span class="st0">&quot;error&quot;</span>
<span class="kw1">end</span></pre></div></div>


<p>It’s not the most elegant solution, but it does the job of ensuring randomness and handling the nitty gritty parts of running a contest.</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/listary-giveaway-get-yours/' rel='bookmark' title='Listary giveaway, get yours!'>Listary giveaway, get yours!</a></li>
<li><a href='http://brettterpstra.com/five-yoink-promo-codes-up-for-grabs/' rel='bookmark' title='Five Yoink promo codes up for grabs!'>Five Yoink promo codes up for grabs!</a></li>
<li><a href='http://brettterpstra.com/ios-giveaway-writeup/' rel='bookmark' title='iOS App Giveaway: WriteUp'>iOS App Giveaway: WriteUp</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/automating-random-giveaways-v1-0/">Automating random giveaways, v1.0</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/automating-random-giveaways-v1-0/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Marked Bonus Pack fix and Marked 1.3 progress</title>
		<link>http://brettterpstra.com/marked-bonus-pack-fix-and-marked-1-3-progress/</link>
		<comments>http://brettterpstra.com/marked-bonus-pack-fix-and-marked-1-3-progress/#comments</comments>
		<pubDate>Wed, 28 Sep 2011 23:00:45 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[markdown]]></category>
		<category><![CDATA[marked]]></category>
		<category><![CDATA[multimarkdown]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/marked-bonus-pack-fix-and-marked-1-3-progress/</guid>
		<description><![CDATA[<p>I just posted a minor update to the Marked Bonus Pack with a few bugfixes for the included Service and AppleScripts. The biggest fix is for the issue some people were having where running the Service would always open TextEdit. I was unable to replicate the problem, but I think I found a solution for it. The Bonus Pack currently&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/marked-bonus-pack-fix-and-marked-1-3-progress/">Marked Bonus Pack fix and Marked 1.3 progress</a></p>]]></description>
			<content:encoded><![CDATA[<p>I just posted a minor update to the <a href="http://support.markedapp.com/kb/how-to-tips-and-tricks/marked-bonus-pack-scripts-commands-and-bundles">Marked Bonus Pack</a> with a few bugfixes for the included Service and AppleScripts. The biggest fix is for the issue some people were having where running the Service would always open TextEdit. I was unable to replicate the problem, but I think I found a solution for it.</p>

<p>The Bonus Pack currently includes scripts and commands for interacting with <a href="http://markedapp.com/">Marked</a> from TextMate, Sublime Text 2, Emacs and Vim, as well as a System Service and AppleScript for opening the current file from Byword, TextEdit, Notational Velocity/nvALT and a fallback for just about any AppleScript-able application.</p>

<p>Once everything is smoothed out to my satisfaction, the Service will likely be included as part of the Marked application, but for now it’s a separate download. The next version of Marked (1.3) is in final beta testing with a few Snow Leopard bugs left to squash. I should be submitting it to the Mac App Store within the week.</p>

<p>Version 1.3 updates to the latest MultiMarkdown build, adds Lion Fullscreen, opens any file extension, handles multiple custom styles, adds a few nice touches (including MathJax) to previews and more. I’m really excited about it, I just want to make sure that all of the new features don’t bring an equal number of new bugs with them.</p>

<p>One feature I’m especially excited about in 1.3 is the ability to watch a custom style’s CSS file in addition to the Markdown (or HTML) file you’re editing. Not only does this make <a href="http://support.markedapp.com/kb/how-to-tips-and-tricks/writing-custom-css-for-marked">creating custom styles</a> much easier, it also opens Marked up to being to web designers what it already is to Markdown writers: a live preview for your HTML/CSS, no matter what editor you’re working in. HTML5/CSS3 compatibility combined with the custom processor (which can be set to run the file through Ruby or PHP, too) makes it a handy addition to a web development toolkit. I’m using it to design a revamp to the Marked website right now, in fact.</p>

<p>If you haven’t checked out Marked yet, take a look at the <a href="http://markedapp.com/">Marked website</a>. I went overboard collecting all of the nice things people were writing and made the page pretty ugly with the press section, but I’m working that out right now. I promise.</p>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/introducing-the-marked-bonus-pack/' rel='bookmark' title='Introducing the Marked Bonus Pack'>Introducing the Marked Bonus Pack</a></li>
<li><a href='http://brettterpstra.com/marked-bonus-pack-1-2/' rel='bookmark' title='Marked Bonus Pack 1.2'>Marked Bonus Pack 1.2</a></li>
<li><a href='http://brettterpstra.com/get-marked-50-off-for-black-friday/' rel='bookmark' title='Get Marked: 50% off for Black Friday'>Get Marked: 50% off for Black Friday</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/marked-bonus-pack-fix-and-marked-1-3-progress/">Marked Bonus Pack fix and Marked 1.3 progress</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/marked-bonus-pack-fix-and-marked-1-3-progress/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Geeklet: Top CPU processes</title>
		<link>http://brettterpstra.com/geeklet-top-cpu-processes/</link>
		<comments>http://brettterpstra.com/geeklet-top-cpu-processes/#comments</comments>
		<pubDate>Fri, 16 Sep 2011 14:00:05 +0000</pubDate>
		<dc:creator>Brett</dc:creator>
				<category><![CDATA[Blog]]></category>
		<category><![CDATA[Code]]></category>
		<category><![CDATA[geeklet]]></category>
		<category><![CDATA[geektool]]></category>
		<category><![CDATA[nerdtool]]></category>
		<category><![CDATA[scripting]]></category>

		<guid isPermaLink="false">http://brettterpstra.com/?p=2800</guid>
		<description><![CDATA[<p>Continuing the series of geeklets I’ve been posting for GeekTool and NerdTool1, here’s my “Top CPU Processes” monitor. This geeklet is pretty useful. It’s effectively like running top on your desktop (but without the overhead) to see what processes are currently taking up the most cycles on your CPU. It works best in combination with a 1 minute CPU load&#8230;</p><p>Originally posted on <a href="http://brettterpstra.com" title="BrettTerpstra.com">BrettTerpstra.com</a> at <a href="http://brettterpstra.com/geeklet-top-cpu-processes/">Geeklet: Top CPU processes</a></p>]]></description>
			<content:encoded><![CDATA[<p><img src="http://cdn2.brettterpstra.com/wp-content/uploads/2011/09/top_cpu_processes.jpg?9d7bd4" alt="Top CPU Processes" /></p>

<p>Continuing the <a href="http://brettterpstra.com/tag/geeklet/">series of geeklets</a> I’ve been posting for <a href="http://projects.tynsoe.org/en/geektool/">GeekTool</a> and <a href="http://mutablecode.com/apps/nerdtool">NerdTool</a><sup id="fnref:fn1"><a href="#fn:fn1" rel="footnote">1</a></sup>, here’s my “Top CPU Processes” monitor.</p>

<p>This geeklet is pretty useful. It’s effectively like running <code>top</code> on your desktop (but without the overhead) to see what processes are currently taking up the most cycles on your CPU. It works best in combination with a <a href="http://brettterpstra.com/geeklet-1-minute-average-cpu-load/">1 minute CPU load monitor</a>. I set this geeklet to update every 5 seconds. Within 5 seconds, things can change a lot, but any process that is taking up a significant portion of the current load will generally stay at the top and offer a clear idea of what might be slowing things down. It generally keeps running when other things start hanging, so it’s much more convenient than using Activity Monitor or <code>top</code> at the command line.</p>

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

<p>The script parses the <code>ps</code> command (<strong>p</strong>rocess <strong>s</strong>tatus, information about all of your processes). It uses the arguments <code>ps -arcwwwxo "command %cpu"</code> to display all processes (including other users’ and processes without terminals) by their executable name, sort by CPU and limit the columns in the output to just the command name and CPU percentage. That handles the bulk of the work right there. The rest of my script simply pulls out the top processes, limiting the number to 10 and cutting it short if there are more than five processes listed at 0%.</p>

<p>It color codes the output based on percentage, giving you red, yellow and blue lines if processes are above 10%, 20%, and 30%, respectively. It also justifies the output, truncating the process name if necessary and adding the percentage in parenthesis with a stretched space to right justify them. In order for the justification to work, you need to use a monospaced font such as Menlo or Droid Sans Mono (Inconsolata looks pretty good, too).</p>

<p>The script accepts one command line argument: <code>-t "title"</code>. If you leave that off, it will automatically put “Top CPU processes” and a newline at the top of the output. If you add <code>-t</code> without an argument after it, it will remove the title entirely. If you use <code>-t "Custom title"</code> it will replace the  default with your custom title (and automatic newline). Any other customization (colors, removing justification) will require manually editing the script. You’re on your own for that.</p>

<p>Here’s the script in its entirety. Just copy and paste it into a file called <code>cpumeter.rb</code>, place it in a script folder and make it executable (<code>chmod a+x cpumeter.rb</code>). Add the path to it as a shell geeklet and you’re good to go. In NerdTool, you may need to specify that the output is colorized.</p>


<div class="wp_syntax"><div class="code"><pre class="ruby"><span class="co1">#!/usr/bin/ruby</span>
&nbsp;
RED = <span class="st0">&quot;<span class="es0">\0</span>33[31m&quot;</span>
GREEN = <span class="st0">&quot;<span class="es0">\0</span>33[32m&quot;</span>
YELLOW = <span class="st0">&quot;<span class="es0">\0</span>33[33m&quot;</span>
BLUE = <span class="st0">&quot;<span class="es0">\0</span>33[34m&quot;</span>
MAGENTA = <span class="st0">&quot;<span class="es0">\0</span>33[35m&quot;</span>
CYAN = <span class="st0">&quot;<span class="es0">\0</span>33[36m&quot;</span>
WHITE = <span class="st0">&quot;<span class="es0">\0</span>33[37m&quot;</span>
DEFAULT=<span class="st0">&quot;<span class="es0">\0</span>33[0;39m&quot;</span>
&nbsp;
<span class="kw1">def</span> spacer<span class="br0">&#40;</span><span class="kw3">string</span><span class="br0">&#41;</span>
	<span class="kw1">if</span> <span class="kw3">string</span>.<span class="me1">length</span> <span class="sy0">&gt;</span> <span class="nu0">15</span>
		<span class="kw3">string</span> = <span class="kw3">string</span><span class="br0">&#91;</span><span class="nu0">0</span> .. <span class="nu0">12</span><span class="br0">&#93;</span> <span class="sy0">+</span> <span class="st0">&quot;…  &quot;</span>
	<span class="kw1">else</span>
		spaces = <span class="nu0">16</span> <span class="sy0">-</span> <span class="kw3">string</span>.<span class="me1">length</span>
		<span class="nu0">0</span>.<span class="me1">upto</span><span class="br0">&#40;</span>spaces<span class="br0">&#41;</span> <span class="kw1">do</span>
			<span class="kw3">string</span> <span class="sy0">+</span>= <span class="st0">&quot; &quot;</span>
		<span class="kw1">end</span>
	<span class="kw1">end</span>
	<span class="kw3">string</span>
<span class="kw1">end</span>
&nbsp;
input = <span class="sy0">%</span>x<span class="br0">&#123;</span>ps <span class="sy0">-</span>arcwwwxo <span class="st0">&quot;command %cpu&quot;</span><span class="br0">&#125;</span>.<span class="kw3">split</span><span class="br0">&#40;</span><span class="st0">&quot;<span class="es0">\n</span>&quot;</span><span class="br0">&#41;</span>
counter, total = <span class="nu0">0</span>, <span class="nu0">0</span>
&nbsp;
title = ARGV<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;-t&quot;</span> ? ARGV<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span> : <span class="st0">&quot;Top CPU processes&quot;</span>
<span class="kw3">print</span> <span class="st0">&quot;#{title}<span class="es0">\n</span><span class="es0">\n</span>&quot;</span> <span class="kw1">unless</span> ARGV<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span> == <span class="st0">&quot;-t&quot;</span> <span class="sy0">&amp;&amp;</span> ARGV<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>.<span class="kw2">nil</span>?
&nbsp;
input.<span class="me1">each</span> <span class="br0">&#123;</span><span class="sy0">|</span>line<span class="sy0">|</span>
	<span class="kw1">if</span> line =~ <span class="sy0">/</span>^<span class="br0">&#40;</span>.<span class="sy0">*</span>?<span class="br0">&#41;</span>\s<span class="sy0">+</span><span class="br0">&#40;</span>\d<span class="br0">&#123;</span><span class="nu0">1</span>,<span class="nu0">3</span><span class="br0">&#125;</span><span class="br0">&#91;</span>\.,<span class="br0">&#93;</span>\d<span class="br0">&#41;</span>$<span class="sy0">/</span>
		<span class="kw3">exit</span> <span class="kw1">if</span> counter == <span class="nu0">5</span> <span class="kw1">or</span> total == <span class="nu0">10</span>
		score = $2.<span class="me1">to_i</span>
		color = <span class="kw1">case</span> score
		   <span class="kw1">when</span> <span class="nu0">0</span>..<span class="nu0">10</span> <span class="kw1">then</span> DEFAULT
		   <span class="kw1">when</span> <span class="nu0">11</span>..<span class="nu0">20</span> <span class="kw1">then</span> CYAN
		   <span class="kw1">when</span> <span class="nu0">21</span>..<span class="nu0">30</span> <span class="kw1">then</span> YELLOW
		   <span class="kw1">when</span> <span class="nu0">30</span>..<span class="nu0">200</span> <span class="kw1">then</span> RED
		   <span class="kw1">else</span> RED
		<span class="kw1">end</span>
&nbsp;
		<span class="kw3">puts</span> <span class="st0">&quot;#{color}#{spacer($1)}(#{$2})<span class="es0">\0</span>33[0m&quot;</span>
&nbsp;
		counter <span class="sy0">+</span>= <span class="nu0">1</span> <span class="kw1">if</span> $2.<span class="me1">to_i</span> <span class="sy0">&lt;</span> <span class="nu0">1</span>
		total <span class="sy0">+</span>= <span class="nu0">1</span>
	<span class="kw1">end</span>
<span class="br0">&#125;</span></pre></div></div>


<p><em>Updated to work with non-US systems</em></p>

<p>Next up, the same type of system monitor, but for physical memory size.</p>

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

<li id="fn:fn1">
<p>If you’re still trying to figure out which you want to run, see <a href="http://www.leancrew.com/all-this/2011/09/nerdtool-over-geektool/">Dr. Drang’s article</a> on the subject. <a href="#fnref:fn1" rev="footnote">↩</a></p>
</li>

</ol>
</div>
<p>Related posts:<ol>
<li><a href='http://brettterpstra.com/geeklet-top-ram-processes/' rel='bookmark' title='Geeklet: Top RAM Processes'>Geeklet: Top RAM Processes</a></li>
<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/quick-tip-throttling-parallel-batch-processes-in-terminal/' rel='bookmark' title='Quick Tip: throttling parallel batch processes in Terminal'>Quick Tip: throttling parallel batch processes in Terminal</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/geeklet-top-cpu-processes/">Geeklet: Top CPU processes</a></p>]]></content:encoded>
			<wfw:commentRss>http://brettterpstra.com/geeklet-top-cpu-processes/feed/</wfw:commentRss>
		<slash:comments>14</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 35/182 queries in 0.495 seconds using xcache
Object Caching 4476/4667 objects using xcache
Content Delivery Network via cdn2.brettterpstra.com

Served from: brettterpstra.com @ 2012-02-09 17:56:56 -->
