<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss 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/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Eric Wendelin's Blog</title>
	
	<link>http://eriwen.com</link>
	<description>Programming productively with open-source tools</description>
	<lastBuildDate>Thu, 05 Nov 2009 15:48:40 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=abc</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<geo:lat>39.929566</geo:lat><geo:long>-104.949317</geo:long><creativeCommons:license>http://creativecommons.org/licenses/by/2.0/</creativeCommons:license><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/EricWendelin" type="application/rss+xml" /><feedburner:emailServiceId>EricWendelin</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Using Python to update your FeedBurner stats</title>
		<link>http://feedproxy.google.com/~r/EricWendelin/~3/G2W32B-a6w4/</link>
		<comments>http://eriwen.com/python/update-feedburner-count/#comments</comments>
		<pubDate>Thu, 05 Nov 2009 11:00:11 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=986</guid>
		<description><![CDATA[<img src="http://eriwen.com/images/html.jpg" style="margin: 0 8px 0 0; float: left;"/>Ever since I've moved to my own server for my websites, I've wanted to reduce the number of HTTP requests per user as much as possible. Here is how I (and you) can use Python to shave 1 more request off that number.

I can do this (and remove a <abbr title="Domain Name Service">DNS</abbr> lookup) by updating my <a href="http://feedburner.google.com">Feedburner</a> count using an automated <strong>script on my server instead of having each client request it.</strong> 

<h2>Using the FeedBurner Awareness API</h2>
Most of the time you only care about getting your total subscribers at the moment. The <a href="http://code.google.com/apis/feedburner/awareness_api.html">FeedBurner Awareness API</a> is far more capable than just doing that, but we're going to keep it simple today. 

For the simple case you just need your feed ID or URI. Try:
[bash]
curl -s 'https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=YOUR_FEED_NAME'
[/bash]

You receive an XML response like:
[xml]
<?xml version="1.0" encoding="UTF-8"?>
<rsp stat="ok">
  <!--This information is part of the FeedBurner Awareness API. If you want to hide this information, you may do so via your FeedBurner Account.-->
  <feed id="foo0nbta7tscktjrgddc95gg3s" uri="EricWendelin">
    <entry date="2009-11-03" circulation="1181" hits="3901" reach="21" />
  </feed>
</rsp>
[/xml]

Now we just need to parse out the "circulation" which is your subscriber count. 


Related posts:<ol><li><a href='http://eriwen.com/python/first-impressions/' rel='bookmark' title='Permanent Link: Python first impressions'>Python first impressions</a></li><li><a href='http://eriwen.com/python/site-monitor/' rel='bookmark' title='Permanent Link: Site monitoring with Python and cron'>Site monitoring with Python and cron</a></li><li><a href='http://eriwen.com/javascript/highlight-search-results-with-js/' rel='bookmark' title='Permanent Link: How to highlight search results with JavaScript and CSS'>How to highlight search results with JavaScript and CSS</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://eriwen.com/images/html.jpg" style="margin: 0 8px 0 0; float: left;"/>Ever since I&#8217;ve moved to my own server for my websites, I&#8217;ve wanted to reduce the number of HTTP requests per user as much as possible. Here is how I (and you) can use Python to <strong>shave 1 more request off that number.</strong></p>
<p>I can do this (and remove a <abbr title="Domain Name Service">DNS</abbr> lookup) by updating my <a href="http://feedburner.google.com">Feedburner</a> count using an automated <strong>script on my server instead of having each client request it.</strong> </p>
<h2>Using the FeedBurner Awareness API</h2>
<p>Most of the time you only care about getting your total subscribers at the moment. The <a href="http://code.google.com/apis/feedburner/awareness_api.html">FeedBurner Awareness API</a> is far more capable than just doing that, but we&#8217;re going to keep it simple today. </p>
<p>For the simple case you just need your feed ID or URI. Try:</p>
<pre class="brush: bash">
curl -s &#039;https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=YOUR_FEED_NAME&#039;
</pre>
<p>You receive an XML response like:</p>
<pre class="brush: xml">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;rsp stat=&quot;ok&quot;&gt;
  &lt;!--This information is part of the FeedBurner Awareness API. If you want to hide this information, you may do so via your FeedBurner Account.--&gt;
  &lt;feed id=&quot;foo0nbta7tscktjrgddc95gg3s&quot; uri=&quot;EricWendelin&quot;&gt;
    &lt;entry date=&quot;2009-11-03&quot; circulation=&quot;1181&quot; hits=&quot;3901&quot; reach=&quot;21&quot; /&gt;
  &lt;/feed&gt;
&lt;/rsp&gt;
</pre>
<p>Now we just need to parse out the &#8220;circulation&#8221; which is your subscriber count. </p>
<h2>Quick and dirty bash script</h2>
<p>This is what I used to use until FeedBurner started returning 0s or blanks in the XML returned: </p>
<pre class="brush: bash">
#!/bin/bash
FEED_COUNT=`curl -s https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=EricWendelin | egrep -o circulation=\&quot;[0-9]+\&quot; | egrep -o [0-9]+`

sed -r -i &quot;s/(\&quot;numsubscribers\&quot;&gt;)[^&lt;]+&lt;/\1$FEED_COUNT&lt;/g&quot; /my/path/to/sidebar.php

echo $FEED_COUNT
</pre>
<p>You can <a href="http://eriwen.com/productivity/crontab-for-automation/">use cron</a> to replace some HTML, log the count, etc. every so often. </p>
<h2>The Python</h2>
<p>The Python version is much lengthier but has error checking and does not have to do file-replacement. The following is also <a href="http://gist.github.com/226407">available on GitHub</a> for your extending pleasure ;).</p>
<pre class="brush: python">
#!/usr/bin/env python

# Usage: ./check_feedburner.py MyFeedName

import re, sys, urllib, fileinput
from xml.dom import minidom

API_URL = &#039;https://feedburner.google.com/api/awareness/1.0/GetFeedData?uri=%s&#039;
# To replace the feed count in a file, put it here
FEED_COUNT_FILE = &#039;/path/to/your/file.php&#039;
# HTML to replace with feed count - REPLACE ME
HTML_REGEX = r&#039;(&quot;numsubscribers&quot;&gt;)[^&lt;]+&lt;&#039;
REPLACE_STRING = r&#039;&quot;numsubscribers&quot;&gt;%s&lt;&#039;

def get_circulation(feed_uri):
    dom = minidom.parse(urllib.urlopen(API_URL % feed_uri))
    entry = dom.getElementsByTagName(&#039;entry&#039;)[0]
    count = entry.getAttribute(&#039;circulation&#039;)
    if count == &#039;&#039; or count == &#039;0&#039;:
     print &#039;Error getting feed count&#039;
     sys.exit(1)
    return count

def replace_feedburner_count(count):
    &#039;&#039;&#039;Replaces feedburner count in FEED_COUNT_FILE&#039;&#039;&#039;
    try:
        for line in fileinput.input(FEED_COUNT_FILE, inplace=1):
     # Comma at the end prevents explicitly writing a newline
            print re.sub(HTML_REGEX, REPLACE_STRING % count, line, 1),
    except OSError, ose:
     print &#039;File &quot;%s&quot; not found&#039; % FEED_COUNT_FILE

if __name__ == &#039;__main__&#039;:
    # First arg is URI
    feed_count = get_circulation(sys.argv[1])
    print feed_count
    if FEED_COUNT_FILE:
        replace_feedburner_count(feed_count)
</pre>
<p>Something like this would be especially cool if you could set thresholds or use <a href="http://docs.python.org/library/optparse.html" title="Python optparse">optparse</a> for advanced options. Useful? Hope so!</p>


<p>Related posts:<ol><li><a href='http://eriwen.com/python/first-impressions/' rel='bookmark' title='Permanent Link: Python first impressions'>Python first impressions</a></li><li><a href='http://eriwen.com/python/site-monitor/' rel='bookmark' title='Permanent Link: Site monitoring with Python and cron'>Site monitoring with Python and cron</a></li><li><a href='http://eriwen.com/javascript/highlight-search-results-with-js/' rel='bookmark' title='Permanent Link: How to highlight search results with JavaScript and CSS'>How to highlight search results with JavaScript and CSS</a></li></ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/EricWendelin?a=G2W32B-a6w4:RZbz87REDsU:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=G2W32B-a6w4:RZbz87REDsU:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=G2W32B-a6w4:RZbz87REDsU:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=G2W32B-a6w4:RZbz87REDsU:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=G2W32B-a6w4:RZbz87REDsU:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=G2W32B-a6w4:RZbz87REDsU:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=G2W32B-a6w4:RZbz87REDsU:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=G2W32B-a6w4:RZbz87REDsU:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/EricWendelin/~4/G2W32B-a6w4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/python/update-feedburner-count/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://eriwen.com/python/update-feedburner-count/</feedburner:origLink></item>
		<item>
		<title>What and why: the tech behind Cheqlist</title>
		<link>http://feedproxy.google.com/~r/EricWendelin/~3/GVmZA9AI-ws/</link>
		<comments>http://eriwen.com/programming/the-tech-behind-cheqlist/#comments</comments>
		<pubDate>Thu, 22 Oct 2009 11:00:04 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Groovy]]></category>
		<category><![CDATA[JavaFX]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Project]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=962</guid>
		<description><![CDATA[After <a href="http://eriwen.com/tools/cheqlist-remember-the-milk-app/" title="Cheqlist: A free, open-source desktop app for Remember The Milk">launching Cheqlist</a> last week, I felt compelled to give you a peek under the covers to see the tools involved and why I chose certain technologies. I hope to give you insight for times where you decide what to work with.

<h2>Getting started</h2>
Before I could really start working on a major project, I had to choose a VCS. I went with <a href="http://mercurial.selenic.com/wiki/">mercurial</a> based on a friend's insistence that I introduce myself to a <abbr title="Distributed Version Control System">DVCS</abbr> (specifically Hg) immediately. I knew what it was but never took time to try it myself. <strong>I am very glad I tried it.</strong>

Looking back, though, I think <strong><a href="http://git-scm.com/">git</a> may have been a (very slightly) better choice</strong>. Regardless, mercurial has served me very well and I strongly encourage anyone who hasn't given a DVCS a spin to do so!


Related posts:<ol><li><a href='http://eriwen.com/tools/cheqlist-remember-the-milk-app/' rel='bookmark' title='Permanent Link: Cheqlist: A free, open-source desktop app for Remember The Milk'>Cheqlist: A free, open-source desktop app for Remember The Milk</a></li><li><a href='http://eriwen.com/groovy/introducing-groovyrtm/' rel='bookmark' title='Permanent Link: Introducing GroovyRTM: A Groovier way to Remember The Milk'>Introducing GroovyRTM: A Groovier way to Remember The Milk</a></li><li><a href='http://eriwen.com/books/staplesofthebookshelf-lifehacker-88-tech-tricks-to-turbocharge-your-day/' rel='bookmark' title='Permanent Link: Lifehacker: 88 tech tricks to turbocharge your day'>Lifehacker: 88 tech tricks to turbocharge your day</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>After <a href="http://eriwen.com/tools/cheqlist-remember-the-milk-app/" title="Cheqlist: A free, open-source desktop app for Remember The Milk">launching Cheqlist</a> last week, I felt compelled to give you a peek under the covers to see the tools involved and why I chose certain technologies. I hope to give you insight for times where you decide what to work with.</p>
<h2>Getting started</h2>
<p>Before I could really start working on a major project, I had to choose a VCS. I went with <a href="http://mercurial.selenic.com/wiki/">mercurial</a> based on a friend&#8217;s insistence that I introduce myself to a <abbr title="Distributed Version Control System">DVCS</abbr> (specifically Hg) immediately. I knew what it was but never took time to try it myself. <strong>I am very glad I tried it.</strong></p>
<p>Looking back, though, I think <strong><a href="http://git-scm.com/">git</a> may have been a (very slightly) better choice</strong>. Regardless, mercurial has served me very well and I strongly encourage anyone who hasn&#8217;t given a DVCS a spin to do so!</p>
<p>After getting some code and tests written, it was time to pick a project host. I chose <a href="http://kenai.com">kenai.com</a> because it integrated well with NetBeans (which is THE <abbr title="Integrated Development Environment">IDE</abbr> for JavaFX), it supported mercurial, and I like the direction Kenai is taking.</p>
<h2>Communicating with Remember The Milk: GroovyRTM</h2>
<p>RTM has a <a href="http://www.rememberthemilk.com/services/api/">REST API</a> that you can use to interact with the service. I decided to start by creating my own Groovy consumer of that API that would do the heavy lifting of interacting with <a href="http://www.rememberthemilk.com/">Remember The Milk</a> so I could keep my options open when looking for a UI technology. </p>
<p><img src="http://eriwen.com/images/groovyrtm.png" style="margin: 0 auto; display: block;" /></p>
<p>I chose <a href="http://groovy.codehaus.org/" title="The Groovy programming language">Groovy</a> because:</p>
<ul style="margin-left: 2em; list-style-type: upper-roman;">
<li>I didn&#8217;t want to write and maintain a lot of code</li>
<li>I wanted to be able compile to Java classes I could use with other languages that run on the <abbr title="Java Virtual Machine">JVM</abbr></li>
<li>It has great utilities for <a href="http://groovy.codehaus.org/Reading+XML+using+Groovy%27s+XmlSlurper">parsing XML</a> and <a href="http://groovy.codehaus.org/HTTP+Builder">making HTTP requests</a></li>
</ul>
<p>In the end, <strong>Groovy totally came through for me</strong>. It did everything I needed and more, easily.</p>
<p>UPDATE: I&#8217;ve been polishing <a href="http://kenai.com/projects/groovyrtm">GroovyRTM</a> a lot since May and I&#8217;m confident in saying it is, by far, the best Java API kit available. If you have suggestions or improvements, <a href="http://eriwen.com/contact/">let me know</a>!</p>
<h2>The UI</h2>
<p><a href="http://www.rememberthemilk.com/services/api/">JavaFX</a> was a natural choice for me since I&#8217;d been playing with it since before it was 1.0. I was eager to develop something more than a demo app with it. The two key features here were:</p>
<ul style="margin-left: 2em; list-style-type: upper-roman;">
<li>Easily using Java classes &#8211; just an import</li>
<li>Deployment to the desktop AND mobile phones (hoping to deploy to Android eventually). I&#8217;m <strong>holding off on mobile</strong> right now because RTM introduced their own Android app which I can&#8217;t compete with (yet)</li>
<li>Java Web Start deployment gave me a lot of goodies for the desktop (title, icon, auto-update etc.)</li>
</ul>
<p>Here is where I thank <a href="http://learnjavafx.typepad.com/" title="Helping you become a JavaFXpert">Jim Weaver</a> and <a href="http://blogs.sun.com/rakeshmenonp/" title="Java, JavaFX and beyond...">Rakesh Menon</a> in particular for their useful JavaFX examples, helping me find a couple bugs, and their suggestions. If you use JavaFX and you&#8217;re not subscribing to their blogs, it&#8217;s time to come out from under that rock. </p>
<p>Frankly, I don&#8217;t think JavaFX was ready for building real applications until version 1.2 (released in June). Even then, including the <a href="http://code.google.com/p/jfxtras/">JFXtras</a> project is a must. <strong>There is no way I could have done this without them.</strong> I still had to create or adapt a few custom components. In all fairness, JavaFX is a young technology and I know that the team is working very, very hard on producing a lot more for JavaFX 1.3. <strong>Oh, and I can&#8217;t wait for the Sun to release the JavaFX visual designer.</strong></p>
<h2>Launch</h2>
<p>Last but not least, I needed to easily make a screencast to introduce Cheqlist. After listening to <a href="http://faceoffshow.com/2009/09/01/episode-32-screencast-showdown/">Faceoff Show&#8217;s excellent screencasting review</a>, I chose <a href="http://screenr.com">Screenr</a>. The only thing that caught me by surprise is that the video didn&#8217;t embed in my aggregation feeds. Could have been my idiot mistake, though.</p>
<p>You can catch <a href="http://screenr.com/vvH">my intro video here</a> if you haven&#8217;t for some reason.</p>
<h2>Updates!</h2>
<ul style="margin-left: 2em; list-style-type: upper-roman;">
<li>Where&#8217;d my edit button go? Oh yeah, you don&#8217;t need it anymore since all task edits occur immediately now.</li>
<li>Create and delete lists (including smart lists)</li>
<li>Toaster looks and acts much better ;)</li>
<li>Cheqlist is now on twitter! Follow <a href="https://twitter.com/cheqlist">@cheqlist</a> for news and updates.</li>
<li>Yet another update: Cheqlist has been approved for the <a href="http://store.java.com">Java Store</a>!</li>
</ul>
<p><a href="http://eriwen.com/cheqlist/Cheqlist.jnlp"><img width="88" height="34" style="border: medium none;" title="Launch Cheqlist via Java Web Start" src="http://eriwen.com/images/webstart.gif" alt="Launch Cheqlist"/></a></p>
<p>In addition, you should know that I&#8217;m currently working on <strong>notes management, minimizing to taskbar icon, and undo functionality</strong>. Anything else you want? Hit me up <a href="http://twitter.com/eriwen/">on twitter</a>, <a href="http://eriwen.com/contact/">email me</a> or discuss in <a href="http://kenai.com/projects/cheqlist/forums/forum">the forum</a>! </p>
<p>What would you have done differently? Comment!</p>


<p>Related posts:<ol><li><a href='http://eriwen.com/tools/cheqlist-remember-the-milk-app/' rel='bookmark' title='Permanent Link: Cheqlist: A free, open-source desktop app for Remember The Milk'>Cheqlist: A free, open-source desktop app for Remember The Milk</a></li><li><a href='http://eriwen.com/groovy/introducing-groovyrtm/' rel='bookmark' title='Permanent Link: Introducing GroovyRTM: A Groovier way to Remember The Milk'>Introducing GroovyRTM: A Groovier way to Remember The Milk</a></li><li><a href='http://eriwen.com/books/staplesofthebookshelf-lifehacker-88-tech-tricks-to-turbocharge-your-day/' rel='bookmark' title='Permanent Link: Lifehacker: 88 tech tricks to turbocharge your day'>Lifehacker: 88 tech tricks to turbocharge your day</a></li></ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/EricWendelin?a=GVmZA9AI-ws:ZXG67DZQb5k:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=GVmZA9AI-ws:ZXG67DZQb5k:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=GVmZA9AI-ws:ZXG67DZQb5k:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=GVmZA9AI-ws:ZXG67DZQb5k:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=GVmZA9AI-ws:ZXG67DZQb5k:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=GVmZA9AI-ws:ZXG67DZQb5k:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=GVmZA9AI-ws:ZXG67DZQb5k:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=GVmZA9AI-ws:ZXG67DZQb5k:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/EricWendelin/~4/GVmZA9AI-ws" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/programming/the-tech-behind-cheqlist/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://eriwen.com/programming/the-tech-behind-cheqlist/</feedburner:origLink></item>
		<item>
		<title>Cheqlist: A free, open-source desktop app for Remember The Milk</title>
		<link>http://feedproxy.google.com/~r/EricWendelin/~3/CpMckLMPph0/</link>
		<comments>http://eriwen.com/tools/cheqlist-remember-the-milk-app/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 11:00:34 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Groovy]]></category>
		<category><![CDATA[JavaFX]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Project]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=939</guid>
		<description><![CDATA[<img src="http://eriwen.com/cheqlist/cheqlist_logo_64.png" style="float: left; margin: 0 8px 0 0; border: 0px solid none;"/>Anyone looking to stay productive with their work, errands or chores keeps a to-do list. You need to have that to-do list available at all times and be easy to manage. 

With that in mind, I am introducing an application that I think will help you with that: <a href="http://eriwen.com/cheqlist/Cheqlist.jnlp">Cheqlist</a>. A desktop application powered by <a href="http://www.rememberthemilk.com/">Remember The Milk</a> that does 2 things very well: make <strong>managing tasks very efficient</strong> and <strong>look sweet</strong> on your desktop.

<h2>What makes Cheqlist awesome</h2>
I wanted to build an application that I, myself, would use everyday. There are a few key features that would make that happen:
<ul style="margin-left: 2em; list-style-type: upper-roman;"><li>Adding tasks quickly using RTM's new <a href="<a href="http://www.rememberthemilk.com/services/smartadd/">Smart Add feature</a></li>
<li>Visual appeal and lots of room for customization. Special thanks to Rakesh Menon for allowing me to use his <a href="http://blogs.sun.com/rakeshmenonp/entry/javafx_color_picker">JavaFX color picker</a></li>
<li>Easily search tasks and use RTM's <a href="http://www.rememberthemilk.com/help/answers/search/advanced.rtm">custom search keywords</a></li>
<li>Must work on all the OSes I use: Windows, Mac OS X, and Linux</li>
</ul>

On top of that, I think there are some things you'll come to appreciate:
<ul style="margin-left: 2em; list-style-type: upper-roman;"><li>Easy-update: Cheqlist checks for updates on startup, and if you want to upgrade, it takes just seconds!</li>
<li>Free and <a href="http://kenai.com/projects/cheqlist/sources" title="Cheqlist source repository">open-source</a></li>
<li>Lots of nice "easter egg" features for those of you who take time to find them ;)</li></ul>



Related posts:<ol><li><a href='http://eriwen.com/groovy/introducing-groovyrtm/' rel='bookmark' title='Permanent Link: Introducing GroovyRTM: A Groovier way to Remember The Milk'>Introducing GroovyRTM: A Groovier way to Remember The Milk</a></li><li><a href='http://eriwen.com/programming/the-tech-behind-cheqlist/' rel='bookmark' title='Permanent Link: What and why: the tech behind Cheqlist'>What and why: the tech behind Cheqlist</a></li><li><a href='http://eriwen.com/productivity/multiple-desktops-to-get-things-done/' rel='bookmark' title='Permanent Link: How I use multiple desktops to get things done'>How I use multiple desktops to get things done</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://eriwen.com/cheqlist/cheqlist_logo_64.png" style="float: left; margin: 0 8px 0 0; border: 0px solid none;"/>Anyone looking to stay productive with their work, errands or chores keeps a to-do list. You need to have that to-do list available at all times and be easy to manage. </p>
<p>With that in mind, I am introducing an application that I think will help you with that: <a href="http://eriwen.com/cheqlist/Cheqlist.jnlp">Cheqlist</a>. A desktop application powered by <a href="http://www.rememberthemilk.com/">Remember The Milk</a> that does 2 things very well: make <strong>managing tasks very efficient</strong> and <strong>look sweet</strong> on your desktop.</p>
<h2>What makes Cheqlist awesome</h2>
<p>I wanted to build an application that I, myself, would use everyday. There are a few key features that would make that happen:</p>
<ul style="margin-left: 2em; list-style-type: upper-roman;">
<li>Adding tasks quickly using RTM&#8217;s new <a href="<a href="http://www.rememberthemilk.com/services/smartadd/">Smart Add feature</a></li>
<li>Visual appeal and lots of room for customization. Special thanks to Rakesh Menon for allowing me to use his <a href="http://blogs.sun.com/rakeshmenonp/entry/javafx_color_picker">JavaFX color picker</a></li>
<li>Easily search tasks and use RTM&#8217;s <a href="http://www.rememberthemilk.com/help/answers/search/advanced.rtm">custom search keywords</a></li>
<li>Must work on all the OSes I use: Windows, Mac OS X, and Linux</li>
</ul>
<p>On top of that, I think there are some things you&#8217;ll come to appreciate:</p>
<ul style="margin-left: 2em; list-style-type: upper-roman;">
<li>Easy-update: Cheqlist checks for updates on startup, and if you want to upgrade, it takes just seconds!</li>
<li>Free and <a href="http://kenai.com/projects/cheqlist/sources" title="Cheqlist source repository">open-source</a></li>
<li>Lots of nice &#8220;easter egg&#8221; features for those of you who take time to find them ;)</li>
</ul>
<h2>A quick look</h2>
<p>I&#8217;ve created a short (3 minutes) introductory video to show you the main features. UPDATE: Apparently screenr videos don&#8217;t show up in RSS properly. View it <a href="http://screenr.com/vvH" title="Cheqlist intro video">here</a>.</p>
<p><object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='560' height='345' style='margin-left: 10px;'><param name='movie' value='http://screenr.com/Content/assets/screenr_0817090731.swf' /><param name='flashvars' value='i=18211' /><param name='allowFullScreen' value='true' /><embed src='http://screenr.com/Content/assets/screenr_0817090731.swf' flashvars='i=18211' allowFullScreen='true' width='560' height='345' pluginspage='http://www.macromedia.com/go/getflashplayer'></embed></object></p>
<p>Here are a few screenshots:<br />
<img src="http://eriwen.com/images/cheqlist_screen_1.png" alt="Cheqlist Splash Screen and Edit panes"/><br />
<img src="http://eriwen.com/images/cheqlist_screen_2.png" alt="Cheqlist Settings"/></p>
<p>You can find more on the <a href="http://kenai.com/projects/cheqlist/pages/Home">Cheqlist Wiki</a>.</p>
<h2>Try it out!</h2>
<p>What you need:</p>
<ul style="margin-left: 2em; list-style-type: upper-roman;">
<li>A marginally recent (6u11 or newer) version of <a href="http://www.java.com/en/download/index.jsp" title="Download Java">Java</a></li>
<li><a href="http://www.rememberthemilk.com/">Remember The Milk account</a></li>
<li><strong><a href="http://eriwen.com/cheqlist/Cheqlist.jnlp">Launch Cheqlist</a></strong></li>
</ul>
<h2>Other resources</h2>
<p>Something missing? Request a feature at the <a href="http://kenai.com/jira/browse/CHEQLIST" title="Cheqlist JIRA">issue tracker</a>. </p>
<p>Having trouble? Check out the <a href="http://kenai.com/projects/cheqlist/forums/forum" title="Cheqlist support forums">support forums</a> or <a href="http://eriwen.com/contact/">contact me</a> directly. </p>
<p>For more information, you can hit the <a href="http://kenai.com/projects/cheqlist">project page</a> and <a href="http://kenai.com/projects/cheqlist/pages/Home">Wiki</a> on Kenai. </p>
<p>Enjoy!</p>


<p>Related posts:<ol><li><a href='http://eriwen.com/groovy/introducing-groovyrtm/' rel='bookmark' title='Permanent Link: Introducing GroovyRTM: A Groovier way to Remember The Milk'>Introducing GroovyRTM: A Groovier way to Remember The Milk</a></li><li><a href='http://eriwen.com/programming/the-tech-behind-cheqlist/' rel='bookmark' title='Permanent Link: What and why: the tech behind Cheqlist'>What and why: the tech behind Cheqlist</a></li><li><a href='http://eriwen.com/productivity/multiple-desktops-to-get-things-done/' rel='bookmark' title='Permanent Link: How I use multiple desktops to get things done'>How I use multiple desktops to get things done</a></li></ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/EricWendelin?a=CpMckLMPph0:BaoiDpl6yMQ:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=CpMckLMPph0:BaoiDpl6yMQ:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=CpMckLMPph0:BaoiDpl6yMQ:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=CpMckLMPph0:BaoiDpl6yMQ:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=CpMckLMPph0:BaoiDpl6yMQ:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=CpMckLMPph0:BaoiDpl6yMQ:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=CpMckLMPph0:BaoiDpl6yMQ:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=CpMckLMPph0:BaoiDpl6yMQ:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/EricWendelin/~4/CpMckLMPph0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/tools/cheqlist-remember-the-milk-app/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://eriwen.com/tools/cheqlist-remember-the-milk-app/</feedburner:origLink></item>
		<item>
		<title>Site monitoring with Python and cron</title>
		<link>http://feedproxy.google.com/~r/EricWendelin/~3/Y1AUbiQDp80/</link>
		<comments>http://eriwen.com/python/site-monitor/#comments</comments>
		<pubDate>Tue, 22 Sep 2009 11:00:23 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=914</guid>
		<description><![CDATA[I recently switched to hosting all of my own websites. While it is liberating to have much more control over my web host, it begs for more maintenance time and better tools to help you monitor your server. 

<image src="http://eriwen.com/images/python_egg_sm.jpg" class="img-left" alt="Baby Python"/>While browsing my <a href="http://github.com/emwendelin">GitHub account</a> I came across <a href="http://www.marksanborn.net">Mark Sanborn</a>'s <a href="http://gist.github.com/177420">site monitoring script</a> and thought: "Hey this is a good idea, let's see what I can make of it". I have been meaning to post more Python here so I updated his code a bit and thought I'd share it with you. I hope you have ideas for improvements.

<h2>Checking site availability with Python</h2>
I didn't feel that this script was big enough to go full <abbr title="Object Oriented">OO</abbr> with it, but if you want to add to it, fork the <a href="http://gist.github.com/187610">gist on GitHub</a> and provide a link in the comments. <strong>You know what'd really be cool is if someone used timeit to get the response time and set thresholds for when the site is too slow.</strong>



Related posts:<ol><li><a href='http://eriwen.com/python/update-feedburner-count/' rel='bookmark' title='Permanent Link: Using Python to update your FeedBurner stats'>Using Python to update your FeedBurner stats</a></li><li><a href='http://eriwen.com/python/first-impressions/' rel='bookmark' title='Permanent Link: Python first impressions'>Python first impressions</a></li><li><a href='http://eriwen.com/groovy/groovy-shell-scripts/' rel='bookmark' title='Permanent Link: Get groovy for better shell scripts'>Get groovy for better shell scripts</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>I recently switched to hosting all of my own websites. While it is liberating to have much more control over my web host, it begs for more maintenance time and better tools to help you monitor your server. </p>
<p><image src="http://eriwen.com/images/python_egg_sm.jpg" class="img-left" alt="Baby Python"/>While browsing my <a href="http://github.com/emwendelin">GitHub account</a> I came across <a href="http://www.marksanborn.net">Mark Sanborn</a>&#8217;s <a href="http://gist.github.com/177420">site monitoring script</a> and thought: &#8220;Hey this is a good idea, let&#8217;s see what I can make of it&#8221;. I have been meaning to post more Python here so I updated his code a bit and thought I&#8217;d share it with you. I hope you have ideas for improvements.</p>
<p class="update">UPDATE: It looks like Mark has made this a full <a href="http://github.com/sanbornm/Site-Monitor">project on GitHub</a> and added timing the requests and command-line options! This is a perfect example of how <acronym title="Open-Source Software">OSS</acronym> projects are started. Check out his <a href="http://www.nixtutor.com/linux/your-chance-to-contribute-to-an-open-source-project/">introductory post</a>.</p>
<h2>Checking site availability with Python</h2>
<p>I didn&#8217;t feel that this script was big enough to go full <abbr title="Object Oriented">OO</abbr> with it, but if you want to add to it, fork the <a href="http://gist.github.com/187610">gist on GitHub</a> and provide a link in the comments. <strong>You know what&#8217;d really be cool is if someone used timeit to get the response time and set thresholds for when the site is too slow.</strong></p>
<pre class="brush: python">
#!/usr/bin/env python

# sample usage: checksites.py yoursite.com othersite.org

import pickle, os, sys, logging
from httplib import HTTPConnection, socket
from smtplib import SMTP

def email_alert(message, status):
    fromaddr = &#039;you@gmail.com&#039;
    toaddrs = &#039;yourphone@txt.att.net&#039;

    server = SMTP(&#039;smtp.gmail.com:587&#039;)
    server.starttls()
    server.login(&#039;you&#039;, &#039;password&#039;)
    server.sendmail(fromaddr, toaddrs, &#039;Subject: %s\r\n%s&#039; % (status, message))
    server.quit()

def get_site_status(url):
    response = get_response(url)
    try:
        if getattr(response, &#039;status&#039;) == 200:
            return &#039;up&#039;
    except AttributeError:
    	pass
    return &#039;down&#039;

def get_response(url):
    &#039;&#039;&#039;Return response object from URL&#039;&#039;&#039;
    try:
        conn = HTTPConnection(url)
        conn.request(&#039;HEAD&#039;, &#039;/&#039;)
        return conn.getresponse()
    except socket.error:
    	return None
    except:
        logging.error(&#039;Bad URL:&#039;, url)
        exit(1)

def get_headers(url):
    &#039;&#039;&#039;Gets all headers from URL request and returns&#039;&#039;&#039;
    response = get_response(url)
    try:
        return getattr(response, &#039;getheaders&#039;)()
    except AttributeError:
    	return &#039;Headers unavailable&#039;

def compare_site_status(prev_results):
    &#039;&#039;&#039;Report changed status based on previous results&#039;&#039;&#039;

    def is_status_changed(url):
    	status = get_site_status(url)
    	friendly_status = &#039;%s is %s&#039; % (url, status)
    	print friendly_status
    	if url in prev_results and prev_results[url] != status:
            logging.warning(status)
            # Email status messages
            email_alert(str(get_headers(url)), friendly_status)
        prev_results[url] = status

    return is_status_changed

def is_internet_reachable():
    &#039;&#039;&#039;Checks Google then Yahoo just in case one is down&#039;&#039;&#039;
    if get_site_status(&#039;www.google.com&#039;) == &#039;down&#039; and get_site_status(&#039;www.yahoo.com&#039;) == &#039;down&#039;:
        return False
    return True

def load_old_results(file_path):
    &#039;&#039;&#039;Attempts to load most recent results&#039;&#039;&#039;
    pickledata = {}
    if os.path.isfile(file_path):
        picklefile = open(file_path, &#039;rb&#039;)
        pickledata = pickle.load(picklefile)
        picklefile.close()
    return pickledata

def store_results(file_path, data):
    &#039;&#039;&#039;Pickles results to compare on next run&#039;&#039;&#039;
    output = open(file_path, &#039;wb&#039;)
    pickle.dump(data, output)
    output.close()

def main(urls):
    # Setup logging to store time
    logging.basicConfig(level=logging.WARNING, filename=&#039;checksites.log&#039;,
            format=&#039;%(asctime)s %(levelname)s: %(message)s&#039;,
            datefmt=&#039;%Y-%m-%d %H:%M:%S&#039;)

    # Load previous data
    pickle_file = &#039;data.pkl&#039;
    pickledata = load_old_results(pickle_file)

    # Check sites only if Internet is_available
    if is_internet_reachable():
    	status_checker = compare_site_status(pickledata)
    	map(status_checker, urls)
    else:
        logging.error(&#039;Either the world ended or we are not connected to the net.&#039;)

    # Store results in pickle file
    store_results(pickle_file, pickledata)

if __name__ == &#039;__main__&#039;:
    # First arg is script name, skip it
    main(sys.argv[1:])
</pre>
<p>Basically, this script just checks if the internet is available, then checks each site. If the previous result is available and is different, it sends an email with the headers received so you might get a good idea what&#8217;s going on. Even cooler, you can use the <a href="http://www.emailtextmessages.com/">email specific to your cell phone carrier</a> to get text messages when your sites&#8217; availability changes.</p>
<p><strong>NOTE: You must have some sort of mailer daemon installed</strong>. See <a href="http://www.nixtutor.com/linux/send-mail-with-gmail-and-ssmtp/">How to setup Gmail with sSMTP</a>. You can try it out by editing the appropriate parts of the script and then doing:</p>
<pre class="brush: bash">
chmod +x checksites.py
./checksites.py eriwen.com yoursite.com
</pre>
<h2>Scheduling it up with cron</h2>
<p>I&#8217;ve already showed you the <a href="http://eriwen.com/productivity/crontab-for-automation/">ins and outs of basic cron scheduling</a>. We can have this run every 5 minutes by typing <code>crontab -e</code> and then adding:</p>
<pre class="brush: bash">
*/5 * * * * ./path/to/checksites.py yourwebsite.com othersite.org
</pre>
<p>What do you think? Tell me how you&#8217;d make it more &#8220;pythonic&#8221; or otherwise improve it in the comments.</p>


<p>Related posts:<ol><li><a href='http://eriwen.com/python/update-feedburner-count/' rel='bookmark' title='Permanent Link: Using Python to update your FeedBurner stats'>Using Python to update your FeedBurner stats</a></li><li><a href='http://eriwen.com/python/first-impressions/' rel='bookmark' title='Permanent Link: Python first impressions'>Python first impressions</a></li><li><a href='http://eriwen.com/groovy/groovy-shell-scripts/' rel='bookmark' title='Permanent Link: Get groovy for better shell scripts'>Get groovy for better shell scripts</a></li></ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/EricWendelin?a=Y1AUbiQDp80:UOlmotJl_qw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=Y1AUbiQDp80:UOlmotJl_qw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=Y1AUbiQDp80:UOlmotJl_qw:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=Y1AUbiQDp80:UOlmotJl_qw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=Y1AUbiQDp80:UOlmotJl_qw:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=Y1AUbiQDp80:UOlmotJl_qw:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=Y1AUbiQDp80:UOlmotJl_qw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=Y1AUbiQDp80:UOlmotJl_qw:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/EricWendelin/~4/Y1AUbiQDp80" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/python/site-monitor/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://eriwen.com/python/site-monitor/</feedburner:origLink></item>
		<item>
		<title>Follow-up: Why programmers should twitter</title>
		<link>http://feedproxy.google.com/~r/EricWendelin/~3/U5fx9yGsM4I/</link>
		<comments>http://eriwen.com/opinion/follow-up-why-programmers-should-twitter/#comments</comments>
		<pubDate>Thu, 03 Sep 2009 11:00:37 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Opinion]]></category>
		<category><![CDATA[Productivity]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=897</guid>
		<description><![CDATA[Last week, I wrote about <a href="http://eriwen.com/opinion/why-programmers-should-twitter/">why programmers should twitter</a>. My article met with heavy criticism at <a href="http://www.dzone.com/links/why_programmers_should_twitter.html">DZone</a>. Today, I intend to answer people's doubts and try to approach the subject from a slightly different angle.

<h2>Not just small talk</h2>
A lot of people seem to think that <a href="http://twitter.com">Twitter</a> is all about "sitting on patios" or "my MBP did these things", and that's understandable. There is a lot of generally useless stuff and <strong>a lot of people just use it for that</strong>. You don't have to. You don't have to follow anyone that only posts that and you certainly don't have to tweet that way. It is what you make of it.



Related posts:<ol><li><a href='http://eriwen.com/opinion/why-programmers-should-twitter/' rel='bookmark' title='Permanent Link: Why programmers should twitter'>Why programmers should twitter</a></li><li><a href='http://eriwen.com/groovy/groovy-shell-scripts/' rel='bookmark' title='Permanent Link: Get groovy for better shell scripts'>Get groovy for better shell scripts</a></li><li><a href='http://eriwen.com/opinion/resolutions-2009/' rel='bookmark' title='Permanent Link: A programmer&#8217;s 2009 resolutions'>A programmer&#8217;s 2009 resolutions</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>Last week, I wrote about <a href="http://eriwen.com/opinion/why-programmers-should-twitter/">why programmers should twitter</a>. My article met with heavy criticism at <a href="http://www.dzone.com/links/why_programmers_should_twitter.html">DZone</a>. Today, I intend to answer people&#8217;s doubts and try to approach the subject from a slightly different angle.</p>
<h2>Not just small talk</h2>
<p>A lot of people seem to think that <a href="http://twitter.com">Twitter</a> is all about &#8220;sitting on patios&#8221; or &#8220;my MBP did these things&#8221;, and that&#8217;s understandable. There is a lot of generally useless stuff and a lot of people just use it for that. <strong>You don&#8217;t have to.</strong> You don&#8217;t have to follow anyone that only posts that and you certainly don&#8217;t have to tweet that way. It is what you make of it.</p>
<h2>Only one piece of the puzzle</h2>
<p>Twitter is great, but it&#8217;s not a good replacement for anything except for the questions you might have asked on IRC. You still should be subscribing and reading DZone and individual programming blogs. You still need to try to make it to your local programming group meetings. You will still need to check out Google Groups or random forums for some answers. If you do it right, though, you can enhance your experience by engaging others who <em>choose</em> to be in community with you.</p>
<div style="float:left;"><image src="http://eriwen.com/images/puzzle_piece.jpg" alt="Puzzle Piece" class="img-left" />
<div xmlns:cc="http://creativecommons.org/ns#" about="http://www.flickr.com/photos/walkn/3812703999/" style="font-size: 0.6em;"><a rel="cc:attributionURL" href="http://www.flickr.com/photos/walkn/">http://www.flickr.com/photos/walkn/</a> / <a rel="license" href="http://creativecommons.org/licenses/by/2.0/">CC BY 2.0</a></div>
</div>
<p>It requires extra effort on your part to sift through posts to find stuff you&#8217;re really interested in. I usually spend <strong>about 20 minutes a day</strong> reading and tweeting. This time doesn&#8217;t come from my work time, but my personal time at home or my lunch break. You might not have that kind of time. You may not have an iWhatever to check it while you&#8217;re waiting for your coffee to brew. Or maybe you just don&#8217;t like people and have no intention of interacting with anything without a screen.</p>
<h2>Don&#8217;t just consume, engage</h2>
<p>I find that a lot of programmers tweet about what they&#8217;re working on and give sneak peeks (because they want opinions) to twitter before any of their stuff hits the mainstream aggregators (<a href="http://dzone.com">DZone</a>, <a href="http://www.reddit.com/r/programming/">Proggit</a>, whatever). The big advantage here is that <strong>this is the point of &#8220;involvement&#8221;</strong>. You tend to play a more active role in the programming community when you have access to things in early stages. Furthermore, you open yourself up to more joint projects because you share a greater connection to mutual followers.</p>
<p><strong>I&#8217;m not saying that you can&#8217;t engage on DZone or whatever, but I am saying that it&#8217;s harder to do so.</strong> For me, all those &#8220;stupid fluff&#8221; tweets get me more in tune with a larger variety of programmers habits and abilities. </p>
<h2>Conclusion</h2>
<p>Obviously, <strong>Twitter is not for everyone.</strong> The bottom line is that <strong>you can&#8217;t knock Twitter until you&#8217;ve given it an honest try</strong>. Like a whole week, not just a skim through someone&#8217;s tweets. It&#8217;s not going to be what you expect but I think most of you can find a way to make it valuable. </p>
<h2>Now, a poll</h2>
<p>I&#8217;m introducing polls (requiring Javascript for you subscribers out there ;) to this blog, starting with &#8220;How useful is twitter to you as a programmer?&#8221;. I want you all to come vote and then comment on why you voted the way you did. <strong>Be specific</strong>, too. This is not going to be a flame war, and I reserve the right to re-word all mean-spirited comments to sound like toddler temper tantrums. </p>


<p>Related posts:<ol><li><a href='http://eriwen.com/opinion/why-programmers-should-twitter/' rel='bookmark' title='Permanent Link: Why programmers should twitter'>Why programmers should twitter</a></li><li><a href='http://eriwen.com/groovy/groovy-shell-scripts/' rel='bookmark' title='Permanent Link: Get groovy for better shell scripts'>Get groovy for better shell scripts</a></li><li><a href='http://eriwen.com/opinion/resolutions-2009/' rel='bookmark' title='Permanent Link: A programmer&#8217;s 2009 resolutions'>A programmer&#8217;s 2009 resolutions</a></li></ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/EricWendelin?a=U5fx9yGsM4I:2sa0hXc87us:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=U5fx9yGsM4I:2sa0hXc87us:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=U5fx9yGsM4I:2sa0hXc87us:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=U5fx9yGsM4I:2sa0hXc87us:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=U5fx9yGsM4I:2sa0hXc87us:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=U5fx9yGsM4I:2sa0hXc87us:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=U5fx9yGsM4I:2sa0hXc87us:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=U5fx9yGsM4I:2sa0hXc87us:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/EricWendelin/~4/U5fx9yGsM4I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/opinion/follow-up-why-programmers-should-twitter/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		<feedburner:origLink>http://eriwen.com/opinion/follow-up-why-programmers-should-twitter/</feedburner:origLink></item>
		<item>
		<title>Why programmers should twitter</title>
		<link>http://feedproxy.google.com/~r/EricWendelin/~3/p_wvhmVSoMY/</link>
		<comments>http://eriwen.com/opinion/why-programmers-should-twitter/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 10:00:54 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Opinion]]></category>
		<category><![CDATA[Productivity]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=883</guid>
		<description><![CDATA[I recently read a poll about why people use <a href="http://twitter.com">twitter</a>. It was very interesting seeing the reasons people gave and I'd like to share my thoughts on why you should, too.

You might be laughing to yourself if you already do tweet, but you'd be surprised at how many don't.

<h2>Network with other programmers</h2>
I've <a href="http://eriwen.com/opinion/key-to-programmer-success/">said before</a> that networking is one of the best things you can do for your career. Not only can networking help you find a job, but I've found that programmers are generally very helpful and accessible on twitter. <strong>Programmers love it when you ask about a project they are involved with.</strong> Call it an ego thing.

<img src="http://eriwen.com/images/twitterlogo.png" class="img-left" alt="Twitter Logo" />One other really cool networking use for twitter: <strong>having something to talk about</strong> when you meet at JUGs or conferences. A follow request is an instant icebreaker and gets the networking process started for you. 



Related posts:<ol><li><a href='http://eriwen.com/opinion/follow-up-why-programmers-should-twitter/' rel='bookmark' title='Permanent Link: Follow-up: Why programmers should twitter'>Follow-up: Why programmers should twitter</a></li><li><a href='http://eriwen.com/opinion/resolutions-2009/' rel='bookmark' title='Permanent Link: A programmer&#8217;s 2009 resolutions'>A programmer&#8217;s 2009 resolutions</a></li><li><a href='http://eriwen.com/java/take-advantage-of-javaone/' rel='bookmark' title='Permanent Link: 5 great ways to take advantage of JavaOne'>5 great ways to take advantage of JavaOne</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>I recently read a poll about why people use <a href="http://twitter.com">twitter</a>. It was very interesting seeing the reasons people gave and I&#8217;d like to share my thoughts on why you should, too.</p>
<p>You might be laughing to yourself if you already do tweet, but you&#8217;d be surprised at how many don&#8217;t.</p>
<h2>Network with other programmers</h2>
<p>I&#8217;ve <a href="http://eriwen.com/opinion/key-to-programmer-success/">said before</a> that networking is one of the best things you can do for your career. Not only can networking help you find a job, but I&#8217;ve found that programmers are generally very helpful and accessible on twitter. <strong>Programmers love it when you ask about a project they are involved with.</strong> Call it an ego thing.</p>
<p><img src="http://eriwen.com/images/twitterlogo.png" class="img-left" alt="Twitter Logo" />One other really cool networking use for twitter: <strong>having something to talk about</strong> when you meet at JUGs or conferences. A follow request is an instant icebreaker and gets the networking process started for you. </p>
<h2>Keep up on trends</h2>
<p>You already know that software engineering is a constantly changing field. Twitter is a great way to learn <strong>how and when to branch out</strong> from your areas of focus. Even better, if you have a question about a new technology you can ask your posse without fear. </p>
<p>Be careful, though, there are a TON of cool things out there. Pursuing all of them is idiotic, you&#8217;ll just end up burning yourself out. Trust me ;) </p>
<h2>Promote yourself</h2>
<p>Networking in today&#8217;s world seems to be just as much about <strong>building your personal brand</strong> as meeting others. Hiring managers love to find passionate and honest programmers. There is little better proof than tweets that show you&#8217;re thinking in the programming world (the best proof, though, is open-source code IMO). </p>
<p>Why do you use twitter? Share with a comment or a tweet!</p>
<p><strong>WARNING! Shameless plug:</strong> Don&#8217;t forget to <a href="http://twitter.com/eriwen">follow me on twitter</a>. If you show passion for programming, it&#8217;s likely I&#8217;ll follow you back :)</p>


<p>Related posts:<ol><li><a href='http://eriwen.com/opinion/follow-up-why-programmers-should-twitter/' rel='bookmark' title='Permanent Link: Follow-up: Why programmers should twitter'>Follow-up: Why programmers should twitter</a></li><li><a href='http://eriwen.com/opinion/resolutions-2009/' rel='bookmark' title='Permanent Link: A programmer&#8217;s 2009 resolutions'>A programmer&#8217;s 2009 resolutions</a></li><li><a href='http://eriwen.com/java/take-advantage-of-javaone/' rel='bookmark' title='Permanent Link: 5 great ways to take advantage of JavaOne'>5 great ways to take advantage of JavaOne</a></li></ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/EricWendelin?a=p_wvhmVSoMY:l6V8uN1Lndw:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=p_wvhmVSoMY:l6V8uN1Lndw:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=p_wvhmVSoMY:l6V8uN1Lndw:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=p_wvhmVSoMY:l6V8uN1Lndw:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=p_wvhmVSoMY:l6V8uN1Lndw:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=p_wvhmVSoMY:l6V8uN1Lndw:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=p_wvhmVSoMY:l6V8uN1Lndw:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=p_wvhmVSoMY:l6V8uN1Lndw:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/EricWendelin/~4/p_wvhmVSoMY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/opinion/why-programmers-should-twitter/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://eriwen.com/opinion/why-programmers-should-twitter/</feedburner:origLink></item>
		<item>
		<title>Introducing GroovyRTM: A Groovier way to Remember The Milk</title>
		<link>http://feedproxy.google.com/~r/EricWendelin/~3/ybWPXY2YHbc/</link>
		<comments>http://eriwen.com/groovy/introducing-groovyrtm/#comments</comments>
		<pubDate>Thu, 25 Jun 2009 10:00:28 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Groovy]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Project]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=866</guid>
		<description><![CDATA[I have always wanted to give something back to the wonderful creators of the <a href="http://www.rememberthemilk.com">Remember The Milk</a> to-do list service. It has been a great tool for me the past couple years by helping me keep organized. Thank you, RTM crew!

Over the last couple months I've been taking a bit of spare time to write something that I hope all of us can benefit from: <a href="http://kenai.com/projects/groovyrtm">GroovyRTM</a>

<h2>What is GroovyRTM?</h2>
GroovyRTM allows you to easily take advantage of the <a href="http://www.rememberthemilk.com/services/api/">Remember The Milk REST API</a> using any language on the JVM. In short, you can now write apps for Remember The Milk without having to worry about all the HTTP transaction stuff, error handling, etc. As its name implies, it's written in Groovy, which made it much easier to write and test.


Related posts:<ol><li><a href='http://eriwen.com/tools/cheqlist-remember-the-milk-app/' rel='bookmark' title='Permanent Link: Cheqlist: A free, open-source desktop app for Remember The Milk'>Cheqlist: A free, open-source desktop app for Remember The Milk</a></li><li><a href='http://eriwen.com/programming/the-tech-behind-cheqlist/' rel='bookmark' title='Permanent Link: What and why: the tech behind Cheqlist'>What and why: the tech behind Cheqlist</a></li><li><a href='http://eriwen.com/groovy/crush-images-with-groovy/' rel='bookmark' title='Permanent Link: Crush images on the command-line with Groovy'>Crush images on the command-line with Groovy</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p>I have always wanted to give something back to the wonderful creators of the <a href="http://www.rememberthemilk.com">Remember The Milk</a> to-do list service. It has been a great tool for me the past couple years by helping me keep organized. Thank you, RTM crew!</p>
<p>Over the last couple months I&#8217;ve been taking a bit of spare time to write something that I hope all of us can benefit from: <a href="http://kenai.com/projects/groovyrtm">GroovyRTM</a></p>
<h2>What is GroovyRTM?</h2>
<p>GroovyRTM allows you to easily take advantage of the <a href="http://www.rememberthemilk.com/services/api/">Remember The Milk REST API</a> using any language on the JVM. In short, you can now write apps for Remember The Milk without having to worry about all the HTTP transaction stuff, error handling, etc. As its name implies, it&#8217;s written in Groovy, which made it much easier to write and test. <img src="http://eriwen.com/images/groovyrtm.png" style="display: block; margin: 0 auto;" alt="Remember The Milk + Groovy = GroovyRTM" /></p>
<h2>How can I use it?</h2>
<p>To get started, you&#8217;ll need 3 things:</p>
<ol>
<li>Download <a href="http://kenai.com/projects/groovyrtm/downloads">groovyrtm-all.jar</a> from the project on <a href="http://kenai.com">kenai.com</a></li>
<li>Request an <a href="http://www.rememberthemilk.com/services/api/keys.rtm">API key</a> (you&#8217;ll probably want an RTM account to test it with, too)</li>
<li>Create a <em>RtmService.properties</em> file as explained in the project <a href="http://kenai.com/projects/groovyrtm/pages/Home">Wiki</a></li>
</ol>
<p class='update'><strong>UPDATE:</strong> I&#8217;ve created a quick-start project that has everything you need to get started quickly! I included an application authorization example because that&#8217;s the first hurdle. <a href='http://kenai.com/projects/groovyrtm/downloads/download/GroovyRtmAuth.zip' title='GroovyRTM quick-start'>Download it here</a></p>
<p>Just how easy is it? Suppose you want to write a little Java app that adds a new task:</p>
<pre class="brush: java">
import org.eriwen.rtm.*;

class MyGroovyRtmTest {
    public static void main(String[] args) {
        RtmService groovyrtm = new RtmService();
        groovyrtm.tasksAdd(&quot;Try GroovyRTM!&quot;);
    }
}
</pre>
<p>It&#8217;s that easy! Now, it&#8217;s a little deceiving because the first time your app runs you have to allow it access via the RTM website. The best part is&#8230; it&#8217;s open source! You can check out the source with Mercurial:</p>
<pre class="brush: bash">
hg clone https://kenai.com/hg/groovyrtm~mercurial groovyrtm
</pre>
<h2>Awesome! Can I help?</h2>
<p>Of course! Get the code, give me suggestions, use it and tell me what you think. I am willing to add people to the project that show me their interest and some good Groovy code. Just hit up the <a href="http://kenai.com/projects/groovyrtm/forums/forum">forum</a> or use my <a href="http://eriwen.com/contact/">contact form</a> for questions or suggestions.</p>
<p>If you think it&#8217;s cool but you can&#8217;t use it, help me get it out there by digging it or voting on your favorite aggregator. </p>


<p>Related posts:<ol><li><a href='http://eriwen.com/tools/cheqlist-remember-the-milk-app/' rel='bookmark' title='Permanent Link: Cheqlist: A free, open-source desktop app for Remember The Milk'>Cheqlist: A free, open-source desktop app for Remember The Milk</a></li><li><a href='http://eriwen.com/programming/the-tech-behind-cheqlist/' rel='bookmark' title='Permanent Link: What and why: the tech behind Cheqlist'>What and why: the tech behind Cheqlist</a></li><li><a href='http://eriwen.com/groovy/crush-images-with-groovy/' rel='bookmark' title='Permanent Link: Crush images on the command-line with Groovy'>Crush images on the command-line with Groovy</a></li></ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/EricWendelin?a=ybWPXY2YHbc:O0CgtXp4VO0:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=ybWPXY2YHbc:O0CgtXp4VO0:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=ybWPXY2YHbc:O0CgtXp4VO0:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=ybWPXY2YHbc:O0CgtXp4VO0:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=ybWPXY2YHbc:O0CgtXp4VO0:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=ybWPXY2YHbc:O0CgtXp4VO0:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=ybWPXY2YHbc:O0CgtXp4VO0:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=ybWPXY2YHbc:O0CgtXp4VO0:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/EricWendelin/~4/ybWPXY2YHbc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/groovy/introducing-groovyrtm/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		<feedburner:origLink>http://eriwen.com/groovy/introducing-groovyrtm/</feedburner:origLink></item>
		<item>
		<title>Effective bash shorthand</title>
		<link>http://feedproxy.google.com/~r/EricWendelin/~3/0ifKRhLK5V4/</link>
		<comments>http://eriwen.com/bash/effective-shorthand/#comments</comments>
		<pubDate>Fri, 29 May 2009 08:00:32 +0000</pubDate>
		<dc:creator>Eric Wendelin</dc:creator>
				<category><![CDATA[Bash]]></category>
		<category><![CDATA[Productivity]]></category>

		<guid isPermaLink="false">http://eriwen.com/?p=811</guid>
		<description><![CDATA[<img class="img-left" src="http://eriwen.com/images/keyboard_shell.jpg" alt="" />Let me tell you how to maximize your productivity on the Bourne Again SHell while minimizing your effort. <strong>bash has a ton of tricks and shortcuts</strong> that allow you to command it with little effort, and I intend to show you the features that help me day in and day out.

Today I'm going to explain the use of features like history, brace and file expansion, and other tricks by example and give you references for later. 

<h2>Master your history</h2>
Those who don't know their history are doomed to repeat it. This is arguably one of the best productivity enhancing features of any shell.

You can check your history with the <code>history</code> command, which prints your entire history by default. Alternatively, you can filter the list with:
[bash]
history 10  # prints last 10 entries
history &#124; grep cmd  # searches history for cmd
[/bash]
Each entry has a number, which you can then execute with <code>!&#60;number&#62;</code>

Now suppose I want to copy a file to a directory and then change to that directory. The quick way to do that with history is:
[bash]
cp myfile.txt my/directory/path
cd !$  # cd my/directory/path
[/bash]

or if I forget to run a command as super-user:
[bash]
vi /etc/fstab  # oops!
sudo !!  # sudo vi /etc/fstab
[/bash]



Related posts:<ol><li><a href='http://eriwen.com/tools/grep-is-a-beautiful-tool/' rel='bookmark' title='Permanent Link: grep is a beautiful tool'>grep is a beautiful tool</a></li><li><a href='http://eriwen.com/productivity/aliases-and-functions/' rel='bookmark' title='Permanent Link: Using aliases and command-line functions for speed'>Using aliases and command-line functions for speed</a></li><li><a href='http://eriwen.com/productivity/crontab-for-automation/' rel='bookmark' title='Permanent Link: Start using crontab for automation'>Start using crontab for automation</a></li></ol>]]></description>
			<content:encoded><![CDATA[<p><img class="img-left" src="http://eriwen.com/images/keyboard_shell.jpg" alt="" />Let me tell you how to maximize your productivity on the Bourne Again SHell while minimizing your effort. <strong>bash has a ton of tricks and shortcuts</strong> that allow you to command it with little effort, and I intend to show you the features that help me day in and day out.</p>
<p>Today I&#8217;m going to explain the use of features like history, brace and file expansion, and other tricks by example and give you references for later. </p>
<h2>Master your history</h2>
<p>Those who forget history are doomed to repeat it. This is arguably one of the best productivity enhancing features of any shell.</p>
<p>You can check your history with the <code>history</code> command, which prints your last 500 commands (or so) by default. Alternatively, you can filter the list:</p>
<pre class="brush: bash">
# Print last 10 entries
history 10

# searches history for cmd
history | grep cmd
</pre>
<p>Each entry has a number, which you can then execute with <code>!&lt;number&gt;</code></p>
<p>Now suppose I want to copy a file to a directory and then change to that directory. The quick way to do that with history is:</p>
<pre class="brush: bash">
cp myfile.txt my/directory/path
cd !$  # cd my/directory/path
</pre>
<p>or if I forget to run a command as super-user:</p>
<pre class="brush: bash">
vi /etc/fstab  # oops!
sudo !!  # sudo vi /etc/fstab
</pre>
<p>to execute the last command starting with &quot;mount&quot;, since I don&#8217;t want to type it all out:</p>
<pre class="brush: bash">
# Previously...
mount 192.168.0.100:/my/path/to/music /media/music

# Later...
!mount
# Repeats last mount command
</pre>
<p>Note that I <strong>often (but not always) prefer <code>Ctrl-R</code></strong>, which will search history as you type. As an added bonus you can view the command before executing it.</p>
<p>Other examples:</p>
<pre class="brush: bash">
eric@sawyer:~$ echo foo -a bar baz
foo -a bar baz
eric@sawyer:~$ echo !:3-4
bar baz
eric@sawyer:~$ !-2 #2nd-to-last command
foo -a bar baz
eric@sawyer:~$ ^ba^ya #replace 1st &quot;ba&quot; with &quot;ya&quot;
foo -a yar baz
eric@sawyer:~$ !^:p #MUCH cooler than &quot;echo ...&quot; ;)
foo
eric@sawyer:~$ !?bar #Last command containing &quot;bar&quot;
foo -a bar baz
eric@sawyer:~$ !:gs/ba/ya #replace all &quot;ba&quot; with &quot;ya&quot;
foo -a yar yaz
</pre>
<h3>Quick reference</h3>
<table>
<tbody>
<tr>
<td><code>!!</code></td>
<td>expands to the last command and all arguments</td>
</tr>
<tr>
<td><code>!-3</code></td>
<td>3rd-to-last command and all arguments</td>
</tr>
<tr>
<td><code>!^</code></td>
<td>first argument of the last command in history</td>
</tr>
<tr>
<td><code>!:2</code></td>
<td>2nd argument of the last command</td>
</tr>
<tr>
<td><code>!$</code></td>
<td>last argument of the last command</td>
</tr>
<tr>
<td><code>!*</code></td>
<td>all arguments of the last command, but not the command itself</td>
</tr>
<tr>
<td><code>!42</code></td>
<td>expands to the 42nd command in the history list</td>
</tr>
<tr>
<td><code>!foo</code></td>
<td>last command beginning with &quot;foo&quot;</td>
</tr>
<tr>
<td><code>!?baz</code></td>
<td>last command containing &quot;baz&quot;</td>
</tr>
<tr>
<td><code>^foo^bar</code></td>
<td>last command with the <em>first</em> occurrence of &quot;foo&quot; replaced with &quot;bar&quot;</td>
</tr>
<tr>
<td><code>!:gs/foo/bar</code></td>
<td>last command with <em>all</em> occurrences of &quot;foo&quot; replaced with &quot;bar&quot;</td>
</tr>
<tr>
<td><code>&lt;any_above&gt;:p</code>&nbsp;&nbsp;</td>
<td>prints command without executing</td>
</tr>
</tbody>
</table>
<p><a href="http://eriwen.com/downloads/history_cheatsheet.pdf">Download as PDF</a></p>
<h3>Helpful .bashrc entries for history</h3>
<p>Copy and paste these into <code>~/.bashrc</code></p>
<pre class="brush: bash">
# Don&#039;t put duplicate lines in the history
export HISTCONTROL=ignoredups
# Ignore successive duplicate entries.
export HISTCONTROL=ignoreboth

# Store a lot history entries in a file for grep-age
shopt -s histappend
export HISTFILE=~/long_history
export HISTFILESIZE=50000

# No reason not to save a bunch in history
# Takes up several more MBs of RAM now, oOOOooh
export HISTSIZE=9999

# Ignore dupe commands and other ones you don&#039;t care about
export HISTIGNORE=&quot;&amp;:[ ]*:exit&quot;
</pre>
<h3>Another neat trick with .inputrc</h3>
<p>If you are still particularly fond of the up and down arrows, copy and paste the following into a <code>~/.inputrc</code> file. This will allow you to start typing a command and then hit the up-arrow to search backwards through your history for commands starting with what you typed. I prefer other methods usually but this is pretty cool, huh?</p>
<pre class="brush: bash">
&quot;\eOA&quot;: history-search-backward
&quot;\e[A&quot;: history-search-backward
&quot;\eOB&quot;: history-search-forward
&quot;\e[B&quot;: history-search-forward
&quot;\eOC&quot;: forward-char
&quot;\e[C&quot;: forward-char
&quot;\eOD&quot;: backward-char
&quot;\e[D&quot;: backward-char
</pre>
<h3>Further reading</h3>
<p>Peteris Krumins has an excellent write-up called <a href="http://www.catonmat.net/blog/the-definitive-guide-to-bash-command-line-history">The Definitive Guide to Bash Command Line History</a> which goes in-depth on many of the above topics, should you crave more bash history goodness. </p>
<h2>Brace expansions</h2>
<p>No shorthand list would be complete without the (in)famous brace expansions. Basically, they allow you to specify part(s) of an command to repeat substituting different values of a set within braces. Let me show you what I mean:</p>
<pre class="brush: bash">
# Quickly make a backup
cp file.txt{,.bak}
# Equivalent to &#039;cp file.txt file.txt.back&#039;
</pre>
<p>This is obviously very useful to prevent having to repeat parts of files or directory paths. </p>
<p>Suppose I wanted to make a template folder structure, I could make most of the directories I need with:</p>
<pre class="brush: bash">
mkdir -p {src,test}/com/eriwen/{data,view}
</pre>
<p>This will expand every combination so I end up with src/com/eriwen/data, src/com/eriwen/view, test/com/eriwen/data, and so forth. Being able to create a template directory structure with one line is a big time saver!</p>
<h2>Better filename expansion</h2>
<p>I'm sure you often use the * operator to match files beginning or ending with something, but bash goes far beyond that. It should be noted, though, <strong>at some point a good <code>find | grep</code> is more powerful and useful</strong>. See <a href="http://eriwen.com/productivity/find-is-a-beautiful-tool/">Find is a beautiful tool</a> for more information.</p>
<p>In addition to wildcards with <code>*</code>, you can use <code>?</code> to match any single character. You can also limit matching to certain characters with <code>[]</code>. For example:</p>
<pre class="brush: bash">
ls
# prints &quot;myfile netbeans.conf netbeans-6.5rc2 netbeans-6.5 netbeans-6.7 src&quot;
ls netbeans-6.?
# matches &quot;netbeans-6.5 netbeans-6.7&quot;
ls netbeans-6.[1-5]*
# matches &quot;netbeans-6.5rc2 netbeans-6.5&quot;
</pre>
<h3>.bashrc entries for better filename expansion</h3>
<pre class="brush: bash">
# Include dot (.) files in the results of expansion
shopt -s dotglob
# Case-insensitive matching for filename expansion
shopt -s nocaseglob
# Enable extended pattern matching
shopt -s extglob
</pre>
<h2>cd shorthand</h2>
<p>There are a couple quick tricks to change to oft-used directories. For example:</p>
<pre class="brush: bash">
# Lame way to go home
cd ~

# The cool way
cd
</pre>
<p>You can also switch to the previous directory with <code>cd -</code> like so:</p>
<pre class="brush: bash">
pwd  # prints /home/eriwen/src
cd /my/webserver/directory

# Do something...

cd -
# Now I&#039;m back in /home/eriwen/src
</pre>
<p>To get more advanced with this, try <a href="http://eriwen.com/bash/pushd-and-popd/">mastering your directory stack with pushd and popd</a>. </p>
<h2>Conclusion</h2>
<p>Effective use of history, brace expansions, and other shortcuts will to save you a lot of time. However, <strong>nothing is more productive than no typing</strong>. <a href="http://eriwen.com/productivity/crontab-for-automation/">Automating things</a> is best where possible. If you can't automate, <a href="http://eriwen.com/productivity/aliases-and-functions/">use smart aliases</a>. </p>
<p>I know I did not cover tilde expansions, shell parameter expansions or <a href="http://beerpla.net/2008/12/22/mastering-the-linux-shell-bash-shortcuts-explained/">bash key commands</a>. You will want to check those out as well, but I find them less useful than what I've covered here. </p>
<p>Have any quick shortcuts you love? Share them in the comments!</p>


<p>Related posts:<ol><li><a href='http://eriwen.com/tools/grep-is-a-beautiful-tool/' rel='bookmark' title='Permanent Link: grep is a beautiful tool'>grep is a beautiful tool</a></li><li><a href='http://eriwen.com/productivity/aliases-and-functions/' rel='bookmark' title='Permanent Link: Using aliases and command-line functions for speed'>Using aliases and command-line functions for speed</a></li><li><a href='http://eriwen.com/productivity/crontab-for-automation/' rel='bookmark' title='Permanent Link: Start using crontab for automation'>Start using crontab for automation</a></li></ol></p><div class="feedflare">
<a href="http://feeds.feedburner.com/~ff/EricWendelin?a=0ifKRhLK5V4:ICqE_ze8KB8:F7zBnMyn0Lo"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=0ifKRhLK5V4:ICqE_ze8KB8:F7zBnMyn0Lo" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=0ifKRhLK5V4:ICqE_ze8KB8:cGdyc7Q-1BI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=cGdyc7Q-1BI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=0ifKRhLK5V4:ICqE_ze8KB8:gIN9vFwOqvQ"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=0ifKRhLK5V4:ICqE_ze8KB8:gIN9vFwOqvQ" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=0ifKRhLK5V4:ICqE_ze8KB8:I9og5sOYxJI"><img src="http://feeds.feedburner.com/~ff/EricWendelin?d=I9og5sOYxJI" border="0"></img></a> <a href="http://feeds.feedburner.com/~ff/EricWendelin?a=0ifKRhLK5V4:ICqE_ze8KB8:D7DqB2pKExk"><img src="http://feeds.feedburner.com/~ff/EricWendelin?i=0ifKRhLK5V4:ICqE_ze8KB8:D7DqB2pKExk" border="0"></img></a>
</div><img src="http://feeds.feedburner.com/~r/EricWendelin/~4/0ifKRhLK5V4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://eriwen.com/bash/effective-shorthand/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		<feedburner:origLink>http://eriwen.com/bash/effective-shorthand/</feedburner:origLink></item>
	</channel>
</rss>
