Go build and install on save in SublimeText3

Update: Turns out every new Go developer makes this mistake. I realized the err of my ways with a week of writing this. When you just accept the Go way, everything gets better. Ignore my stupidity below.

Recently I have been dabbling more and more with go. And I write my go apps in SublimeText3. Soon after starting this I found the awesome SublimeGo plugin. So without knowing much, this makes life a lot easier. What I especially enjoy is the ability to run an argument on save. So every time I save a go file, it can do something. At first this ran a build . errors && go vet. But then I wanted a bit more. I wanted it run that, then if successful build the app and move the compiled app to my bin directory.

Unfortunately, the one sucky part of golang is the opinionated way it wants you to organize your filesystem. If you want to keep all your projects together, then your bin directory is going to be required to be in a certain place. The build command claims to allow an output directory with -o but that doesn’t actually work the way it’s documented.

But I managed to find a workaroud and thought I would share. I just build to the current directory then move the file that has the same name as the current directory to my ~/bin which is already in my path. Its not perfect since a file briefly appears in my ST sidebar, but it works.

Here is my full GoSublime.sublime-settings file:

 

 

 

It’s always good when I can finish my goals for the day

I had two goals for today…yes, it’s a holiday and I had goals. My wife is working today so I figured I might as well work on a few fun things. OK, now one of those things is actually work-related, but that’s what you get when you enjoy what you do. 

So here they are:

  1. Finish up the Datadoghq.com Vagrant box
  2. Migrate Technovangelist.com from Squarespace to WordPress on Digital Ocean

Let me walk you through a bit of that. The first item is the continuation of a project that I had been working on for a while. I spent Christmas with my in-laws and with my parents in Detroit and Seattle. In between far too many family visits to count, I started working on adapting a git deploy workflow for the Datadog corporate website. This meant getting everything set up for developing locally. And that meant requiring Apache, PHP, and mysql on the local machine.

I have this configured on my machine, but one of the main reasons for going through this process was to ensure it was easy for anyone to work with. After working with one dev on setting up their local machine, I was frustrated. Then on Friday one of my colleagues, Mike Fiedler, suggested going the Vagrant/Chef route. 

Of course!!! So I started down the rabbit hole and tumbled faster and faster as I went. Every step I made inspired another turn and with every turn I experienced the joy of solving a puzzle and the grief of creating another. But finally this morning I had a single repo to clone, then run a script and within a few minutes both production and staging are ready to go; ready for your improvements. I am psyched!!

So the other goal was pretty easy: migrate off of Squarespace. Why do I want to do this? Squarespace didn’t do anything wrong, but for the functionality it provides, its just a bit too expensive. I pay $20 per month and have paid that or something similar for about 10 years. Normally that would be fine. But I have hosted another two sites on a Digital Ocean droplet for $5 per month (total, not each). When I signed up for sqsp, I wanted to stop managing my own server. Back then it was harder. Plus my server was hand built by me, then later on it was Community Server and Graffiti. Squarespace was easy. And it wasn’t that much more than what I was paying. Well, except when I was at Microsoft and at the time they were running their own hosting which was free for employees. 

So I started another site on my multisite install of WordPress which took all of a minute. Then exported my content from Squarespace…saying it took a minute would be an exaggeration. Importing it to WordPress was super easy. And I had a theme I liked that I spent a little while customizing. All that was left was a simple DNS change and now the site is live. I’ll give it a few days then will cut the cord with Squarespace.

I, Sublime – A Look at My Favorite Sublime Text Plugins

I have been using Sublime Text 2 since pretty close to the beginning. I purchased it early because I could see the value easily and prefer to support the developers who support my efforts.

One of the aspects of Sublime that I love the most are the plugins. But when you get started with Sublime Text 2, it can be difficult to know which plugins to use. This article will go through the ones I think you need to install first.

  • Sublime Package Control – Will Bond’s Package Control is the first thing everyone needs to install. Installing packages without this is a PITA. Even if you only install one other plugin, this is totally worth it! Install it now using the instructions found here.
  • Advanced New File – Easily create new files from the root of your project rather than from the default directory for the app.
  • Alternative Autocompletion – Install this then press escape to cycle through the various autocomplete possibilities.
  • Bracket Highlighter – Quickly seeing the other side of the set of brackets is very useful
  • Emmet – This used to be called ZenCoding. Not sure why it changed, but Zen was breaking down for me and Emmet makes everything better. If you are writing ANY html, install this and get it done quicker!
  • ERB Insert and Toggle Commands – If you are doing any Rails dev, then you are writing ERB files. If you are writing ERB files, you have to keep typing <% %>. Everytime I do that, my finger searches for the % key. Now I press a simple shortcut and cycle between <% %>, <%= %>. <%- %>
  • ERB Snippets – More ERB goodness. Some overlap with the Insert/Toggle plugin, but thats still easier for me.
  • Find Key Conflicts – As soon as you install a few plugins, there will be key conflicts. This helps you find them and more importantly, fix them.
  • GitGutter – I don’t really use the Git plugin since going from the command line is easier when you get used to it, but seeing what lines changed in the gutter is way cool!
  • LiveReload – Save a file and see your browser auto-refresh. When doing Rails, this seems to work better for me than CodeKit, though I still use that occasionally for regular web dev. Follow the instructions here if it crashes on save every now and then.
  • Sidebar Enhancements – This makes the sidebar infinitely more usable!
  • Synced Sidebar – I am fairly new to Rails so still getting a feel for where files are. I tend to open files pressing Command-P then type the file name. When I do, this plugin shows me where in the sidebar the file came from.

If you are doing anything with Rails, I suggest you also look at MHartl’s SublimeText Setup Instructions for some good pointers. I took the RailsCasts Theme from this online theme editor and made the keywords, constants, and library functions a bit lighter because I couldn’t see that shade of red very well.

Do you have any favorite plugins I should be using? Share them in the comments, or send me a tweet @technovangelist

Graphing With R

I took a few days off for Christmas in San Antonio with my parents and my sister. While there, I had the usual tasks for a geek with non-geek relatives: fix computers, fix wifi, fix printers, explain the Internet, explain how stuff works. But in between time spent doing that, and doing family stuff, I learned a bit about R. R is programming language mostly intended to do statistical programming. I don’t know much about that, but I wanted a way to make some graphs that are sometimes difficult to make in Excel.

I think it would be easier to just learn more about Excel, but now I am invested so I am trying to use it as much as possible. Recently at work I added a post to our blog on the impact of JavaScript and concatenating/minifying the code on your website. You can read the about it here At the end of that post, I added an chart describing the final results.

JavaScript tests chart built with R

JavaScript tests chart built with R

Creating a chart like this would probably take me 20-30 minutes in Excel. Building it in R would probably take less time if I knew R like I know Excel. Instead it took me a lot longer. But in getting there I discovered a lot of ways I didn’t like the image. I think Excel is great when you know exactly how you want the final image to appear in the post. I thought I did, but this looks vastly different from that initial version. Tweaking and then having a very repeatable chart within seconds for any dataset is one of R‘s biggest strengths for me.

So how did I get here? Well, R is complicated. Luckily a course on Coursera came up at exactly the right time for me. There is a second course that takes this further that starts next week too.

But assuming that you know the basics of R and just want to see what I did, here is my R Script for this chart (the csv files I am using are the standard ones you can download after running a test on Yottaa):

body, td {
font-family: sans-serif;
background-color: white;
font-size: 12px;
margin: 8px;
}

tt, code, pre {
font-family: ‘DejaVu Sans Mono’, ‘Droid Sans Mono’, ‘Lucida Console’, Consolas, Monaco, monospace;
}

h1 {
font-size:2.2em;
}

h2 {
font-size:1.8em;
}

h3 {
font-size:1.4em;
}

h4 {
font-size:1.0em;
}

h5 {
font-size:0.9em;
}

h6 {
font-size:0.8em;
}

a:visited {
color: rgb(50%, 0%, 50%);
}

pre {
margin-top: 0;
max-width: 95%;
border: 1px solid #ccc;
white-space: pre-wrap;
}

pre code {
display: block; padding: 0.5em;
}

code.r, code.cpp {
background-color: #F8F8F8;
}

table, td, th {
border: none;
}

blockquote {
color:#666666;
margin:0;
padding-left: 1em;
border-left: 0.5em #EEE solid;
}

hr {
height: 0px;
border-bottom: none;
border-top-width: thin;
border-top-style: dotted;
border-top-color: #999999;
}

@media print {
* {
background: transparent !important;
color: black !important;
filter:none !important;
-ms-filter: none !important;
}

body {
font-size:12pt;
max-width:100%;
}

a, a:visited {
text-decoration: underline;
}

hr {
visibility: hidden;
page-break-before: always;
}

pre, blockquote {
padding-right: 1em;
page-break-inside: avoid;
}

tr, img {
page-break-inside: avoid;
}

img {
max-width: 100% !important;
}

@page :left {
margin: 15mm 20mm 15mm 10mm;
}

@page :right {
margin: 15mm 10mm 15mm 20mm;
}

p, h2, h3 {
orphans: 3; widows: 3;
}

h2, h3 {
page-break-after: avoid;
}
}

pre .operator,
pre .paren {
color: rgb(104, 118, 135)
}

pre .literal {
color: rgb(88, 72, 246)
}

pre .number {
color: rgb(0, 0, 205);
}

pre .comment {
color: rgb(76, 136, 107);
}

pre .keyword {
color: rgb(0, 0, 255);
}

pre .identifier {
color: rgb(0, 0, 0);
}

pre .string {
color: rgb(3, 106, 7);
}

var hljs=new function(){function m(p){return p.replace(/&/gm,”&”).replace(/</gm,"<")}function f(r,q,p){return RegExp(q,"m"+(r.cI?"i":"")+(p?"g":""))}function b(r){for(var p=0;p<r.childNodes.length;p++){var q=r.childNodes[p];if(q.nodeName=="CODE"){return q}if(!(q.nodeType==3&&q.nodeValue.match(/s+/))){break}}}function h(t,s){var p="";for(var r=0;r<t.childNodes.length;r++){if(t.childNodes[r].nodeType==3){var q=t.childNodes[r].nodeValue;if(s){q=q.replace(/n/g,"")}p+=q}else{if(t.childNodes[r].nodeName=="BR"){p+="n"}else{p+=h(t.childNodes[r])}}}if(/MSIE [678]/.test(navigator.userAgent)){p=p.replace(/r/g,"n")}return p}function a(s){var r=s.className.split(/s+/);r=r.concat(s.parentNode.className.split(/s+/));for(var q=0;q<r.length;q++){var p=r[q].replace(/^language-/,"");if(e[p]){return p}}}function c(q){var p=[];(function(s,t){for(var r=0;r<s.childNodes.length;r++){if(s.childNodes[r].nodeType==3){t+=s.childNodes[r].nodeValue.length}else{if(s.childNodes[r].nodeName=="BR"){t+=1}else{if(s.childNodes[r].nodeType==1){p.push({event:"start",offset:t,node:s.childNodes[r]});t=arguments.callee(s.childNodes[r],t);p.push({event:"stop",offset:t,node:s.childNodes[r]})}}}}return t})(q,0);return p}function k(y,w,x){var q=0;var z="";var s=[];function u(){if(y.length&&w.length){if(y[0].offset!=w[0].offset){return(y[0].offset<w[0].offset)?y:w}else{return w[0].event=="start"?y:w}}else{return y.length?y:w}}function t(D){var A="<"+D.nodeName.toLowerCase();for(var B=0;B”}while(y.length||w.length){var v=u().splice(0,1)[0];z+=m(x.substr(q,v.offset-q));q=v.offset;if(v.event==”start”){z+=t(v.node);s.push(v.node)}else{if(v.event==”stop”){var p,r=s.length;do{r–;p=s[r];z+=(“”)}while(p!=v.node);s.splice(r,1);while(r<s.length){z+=t(s[r]);r++}}}}return z+m(x.substr(q))}function j(){function q(x,y,v){if(x.compiled){return}var u;var s=[];if(x.k){x.lR=f(y,x.l||hljs.IR,true);for(var w in x.k){if(!x.k.hasOwnProperty(w)){continue}if(x.k[w] instanceof Object){u=x.k[w]}else{u=x.k;w="keyword"}for(var r in u){if(!u.hasOwnProperty(r)){continue}x.k[r]=[w,u[r]];s.push(r)}}}if(!v){if(x.bWK){x.b="\b("+s.join("|")+")\s"}x.bR=f(y,x.b?x.b:"\B|\b");if(!x.e&&!x.eW){x.e="\B|\b"}if(x.e){x.eR=f(y,x.e)}}if(x.i){x.iR=f(y,x.i)}if(x.r===undefined){x.r=1}if(!x.c){x.c=[]}x.compiled=true;for(var t=0;t<x.c.length;t++){if(x.c[t]=="self"){x.c[t]=x}q(x.c[t],y,false)}if(x.starts){q(x.starts,y,false)}}for(var p in e){if(!e.hasOwnProperty(p)){continue}q(e[p].dM,e[p],true)}}function d(B,C){if(!j.called){j();j.called=true}function q(r,M){for(var L=0;L<M.c.length;L++){if((M.c[L].bR.exec(r)||[null])[0]==r){return M.c[L]}}}function v(L,r){if(D[L].e&&D[L].eR.test(r)){return 1}if(D[L].eW){var M=v(L-1,r);return M?M+1:0}return 0}function w(r,L){return L.i&&L.iR.test(r)}function K(N,O){var M=[];for(var L=0;L<N.c.length;L++){M.push(N.c[L].b)}var r=D.length-1;do{if(D[r].e){M.push(D[r].e)}r–}while(D[r+1].eW);if(N.i){M.push(N.i)}return f(O,M.join("|"),true)}function p(M,L){var N=D[D.length-1];if(!N.t){N.t=K(N,E)}N.t.lastIndex=L;var r=N.t.exec(M);return r?[M.substr(L,r.index-L),r[0],false]:[M.substr(L),"",true]}function z(N,r){var L=E.cI?r[0].toLowerCase():r[0];var M=N.k[L];if(M&&M instanceof Array){return M}return false}function F(L,P){L=m(L);if(!P.k){return L}var r="";var O=0;P.lR.lastIndex=0;var M=P.lR.exec(L);while(M){r+=L.substr(O,M.index-O);var N=z(P,M);if(N){x+=N[1];r+='‘+M[0]+”“}else{r+=M[0]}O=P.lR.lastIndex;M=P.lR.exec(L)}return r+L.substr(O,L.length-O)}function J(L,M){if(M.sL&&e[M.sL]){var r=d(M.sL,L);x+=r.keyword_count;return r.value}else{return F(L,M)}}function I(M,r){var L=M.cN?’‘:””;if(M.rB){y+=L;M.buffer=””}else{if(M.eB){y+=m(r)+L;M.buffer=””}else{y+=L;M.buffer=r}}D.push(M);A+=M.r}function G(N,M,Q){var R=D[D.length-1];if(Q){y+=J(R.buffer+N,R);return false}var P=q(M,R);if(P){y+=J(R.buffer+N,R);I(P,M);return P.rB}var L=v(D.length-1,M);if(L){var O=R.cN?”“:””;if(R.rE){y+=J(R.buffer+N,R)+O}else{if(R.eE){y+=J(R.buffer+N,R)+O+m(M)}else{y+=J(R.buffer+N+M,R)+O}}while(L>1){O=D[D.length-2].cN?”“:””;y+=O;L–;D.length–}var r=D[D.length-1];D.length–;D[D.length-1].buffer=””;if(r.starts){I(r.starts,””)}return R.rE}if(w(M,R)){throw”Illegal”}}var E=e[B];var D=[E.dM];var A=0;var x=0;var y=””;try{var s,u=0;E.dM.buffer=””;do{s=p(C,u);var t=G(s[0],s[1],s[2]);u+=s[0].length;if(!t){u+=s[1].length}}while(!s[2]);if(D.length>1){throw”Illegal”}return{r:A,keyword_count:x,value:y}}catch(H){if(H==”Illegal”){return{r:0,keyword_count:0,value:m(C)}}else{throw H}}}function g(t){var p={keyword_count:0,r:0,value:m(t)};var r=p;for(var q in e){if(!e.hasOwnProperty(q)){continue}var s=d(q,t);s.language=q;if(s.keyword_count+s.r>r.keyword_count+r.r){r=s}if(s.keyword_count+s.r>p.keyword_count+p.r){r=p;p=s}}if(r.language){p.second_best=r}return p}function i(r,q,p){if(q){r=r.replace(/^((]+>|t)+)/gm,function(t,w,v,u){return w.replace(/t/g,q)})}if(p){r=r.replace(/n/g,”
“)}return r}function n(t,w,r){var x=h(t,r);var v=a(t);var y,s;if(v){y=d(v,x)}else{return}var q=c(t);if(q.length){s=document.createElement(“pre”);s.innerHTML=y.value;y.value=k(q,c(s),x)}y.value=i(y.value,w,r);var u=t.className;if(!u.match(“(\s|^)(language-)?”+v+”(\s|$)”)){u=u?(u+” “+v):v}if(/MSIE [678]/.test(navigator.userAgent)&&t.tagName==”CODE”&&t.parentNode.tagName==”PRE”){s=t.parentNode;var p=document.createElement(“div”);p.innerHTML=”

”;t=p.firstChild.firstChild;p.firstChild.cN=s.cN;s.parentNode.replaceChild(p.firstChild,s)}else{t.innerHTML=y.value}t.className=u;t.result={language:v,kw:y.keyword_count,re:y.r};if(y.second_best){t.second_best={language:y.second_best.language,kw:y.second_best.keyword_count,re:y.second_best.r}}}function o(){if(o.called){return}o.called=true;var r=document.getElementsByTagName(“pre”);for(var p=0;p<r.length;p++){var q=b(r[p]);if(q){n(q,hljs.tabReplace)}}}function l(){if(window.addEventListener){window.addEventListener("DOMContentLoaded",o,false);window.addEventListener("load",o,false)}else{if(window.attachEvent){window.attachEvent("onload",o)}else{window.onload=o}}}var e={};this.LANGUAGES=e;this.highlight=d;this.highlightAuto=g;this.fixMarkup=i;this.highlightBlock=n;this.initHighlighting=o;this.initHighlightingOnLoad=l;this.IR="[a-zA-Z][a-zA-Z0-9_]*";this.UIR="[a-zA-Z_][a-zA-Z0-9_]*";this.NR="\b\d+(\.\d+)?";this.CNR="\b(0[xX][a-fA-F0-9]+|(\d+(\.\d*)?|\.\d+)([eE][-+]?\d+)?)";this.BNR="\b(0b[01]+)";this.RSR="!|!=|!==|%|%=|&|&&|&=|\*|\*=|\+|\+=|,|\.|-|-=|/|/=|:|;|<|<<|<<=||>=|>>|>>=|>>>|>>>=|\?|\[|\{|\(|\^|\^=|\||\|=|\|\||~”;this.ER=”(?![\s\S])”;this.BE={b:”\\.”,r:0};this.ASM={cN:”string”,b:”‘”,e:”‘”,i:”\n”,c:[this.BE],r:0};this.QSM={cN:”string”,b:'”‘,e:'”‘,i:”\n”,c:[this.BE],r:0};this.CLCM={cN:”comment”,b:”//”,e:”$”};this.CBLCLM={cN:”comment”,b:”/\*”,e:”\*/”};this.HCM={cN:”comment”,b:”#”,e:”$”};this.NM={cN:”number”,b:this.NR,r:0};this.CNM={cN:”number”,b:this.CNR,r:0};this.BNM={cN:”number”,b:this.BNR,r:0};this.inherit=function(r,s){var p={};for(var q in r){p[q]=r[q]}if(s){for(var q in s){p[q]=s[q]}}return p}}();hljs.LANGUAGES.cpp=function(){var a={keyword:{“false”:1,”int”:1,”float”:1,”while”:1,”private”:1,”char”:1,”catch”:1,”export”:1,virtual:1,operator:2,sizeof:2,dynamic_cast:2,typedef:2,const_cast:2,”const”:1,struct:1,”for”:1,static_cast:2,union:1,namespace:1,unsigned:1,”long”:1,”throw”:1,”volatile”:2,”static”:1,”protected”:1,bool:1,template:1,mutable:1,”if”:1,”public”:1,friend:2,”do”:1,”return”:1,”goto”:1,auto:1,”void”:2,”enum”:1,”else”:1,”break”:1,”new”:1,extern:1,using:1,”true”:1,”class”:1,asm:1,”case”:1,typeid:1,”short”:1,reinterpret_cast:2,”default”:1,”double”:1,register:1,explicit:1,signed:1,typename:1,”try”:1,”this”:1,”switch”:1,”continue”:1,wchar_t:1,inline:1,”delete”:1,alignof:1,char16_t:1,char32_t:1,constexpr:1,decltype:1,noexcept:1,nullptr:1,static_assert:1,thread_local:1,restrict:1,_Bool:1,complex:1},built_in:{std:1,string:1,cin:1,cout:1,cerr:1,clog:1,stringstream:1,istringstream:1,ostringstream:1,auto_ptr:1,deque:1,list:1,queue:1,stack:1,vector:1,map:1,set:1,bitset:1,multiset:1,multimap:1,unordered_set:1,unordered_map:1,unordered_multiset:1,unordered_multimap:1,array:1,shared_ptr:1}};return{dM:{k:a,i:”</",c:[hljs.CLCM,hljs.CBLCLM,hljs.QSM,{cN:"string",b:"'\\?.",e:"'",i:"."},{cN:"number",b:"\b(\d+(\.\d*)?|\.\d+)(u|U|l|L|ul|UL|f|F)"},hljs.CNM,{cN:"preprocessor",b:"#",e:"$"},{cN:"stl_container",b:"\b(deque|list|queue|stack|vector|map|set|bitset|multiset|multimap|unordered_map|unordered_set|unordered_multiset|unordered_multimap|array)\s*”,k:a,r:10,c:[“self”]}]}}}();hljs.LANGUAGES.r={dM:{c:[hljs.HCM,{cN:”number”,b:”\b0[xX][0-9a-fA-F]+[Li]?\b”,e:hljs.IMMEDIATE_RE,r:0},{cN:”number”,b:”\b\d+(?:[eE][+\-]?\d*)?L\b”,e:hljs.IMMEDIATE_RE,r:0},{cN:”number”,b:”\b\d+\.(?!\d)(?:i\b)?”,e:hljs.IMMEDIATE_RE,r:1},{cN:”number”,b:”\b\d+(?:\.\d*)?(?:[eE][+\-]?\d*)?i?\b”,e:hljs.IMMEDIATE_RE,r:0},{cN:”number”,b:”\.\d+(?:[eE][+\-]?\d*)?i?\b”,e:hljs.IMMEDIATE_RE,r:1},{cN:”keyword”,b:”(?:tryCatch|library|setGeneric|setGroupGeneric)\b”,e:hljs.IMMEDIATE_RE,r:10},{cN:”keyword”,b:”\.\.\.”,e:hljs.IMMEDIATE_RE,r:10},{cN:”keyword”,b:”\.\.\d+(?![\w.])”,e:hljs.IMMEDIATE_RE,r:10},{cN:”keyword”,b:”\b(?:function)”,e:hljs.IMMEDIATE_RE,r:2},{cN:”keyword”,b:”(?:if|in|break|next|repeat|else|for|return|switch|while|try|stop|warning|require|attach|detach|source|setMethod|setClass)\b”,e:hljs.IMMEDIATE_RE,r:1},{cN:”literal”,b:”(?:NA|NA_integer_|NA_real_|NA_character_|NA_complex_)\b”,e:hljs.IMMEDIATE_RE,r:10},{cN:”literal”,b:”(?:NULL|TRUE|FALSE|T|F|Inf|NaN)\b”,e:hljs.IMMEDIATE_RE,r:1},{cN:”identifier”,b:”[a-zA-Z.][a-zA-Z0-9._]*\b”,e:hljs.IMMEDIATE_RE,r:0},{cN:”operator”,b:”|=||<|!|&|\||\$|:",e:hljs.IMMEDIATE_RE,r:0},{cN:"operator",b:"%",e:"%",i:"\n",r:1},{cN:"identifier",b:"",e:"",r:0},{cN:"string",b:'"',e:'"',c:[hljs.BE],r:0},{cN:"string",b:"'",e:"'",c:[hljs.BE],r:0},{cN:"paren",b:"[[({\])}]",e:hljs.IMMEDIATE_RE,r:0}]}};
hljs.initHighlightingOnLoad();

I am having a lot of fun with R so far and I look forward to seeing what I come up with over the next few weeks. I have a series of posts coming up on the Yottaa Blog and plenty of opportunity to post more charts made with R.

Learning R With Coursera

Last week I started taking a new course on Coursera.org. It’s called Computing for Data Analysis and its all about using the R programming language to get a better understanding of large datasets. I work for Yottaa and large datasets are something we deal a lot with. I want to find an interesting way to work with and understand the data collected from all sorts of sites on the internet and I am hoping R is the perfect solution. Unfortunately, its a bit wierd and not all that well documented, so this training course could be just what I need.

The programming assignment from last week already taught me a few commands I hadn’t used before. We are working with a table of numbers describing ozone, temperature and more and we needed to find the mean of the Solar.R value where Ozone was greater than 31 and temperature was greater than 90. At first it took me about 7 lines of code to get this done, but after some searching, managed to get it down to a single beautiful line (which I am sure I would forget if I did not document it here):

Wow, that is cool!

I am looking forward to the second section of the course which starts on Wednesday!

Finding A Job Isn’t That Hard, Just Get The System To Work For YOU

A few months ago I decided it was time to switch things up a bit. I was eager to move back to the US and also eager to work for a startup where I had more control over my place in the company. I wanted an office I could walk to and one that I wanted to go to everyday. And I wanted the office to be in a vibrant, exciting city with an active startup scene.

Sure, I dabbled with a few companies over the last year, but it wasn’t until mid-March of this year that I started to get a bit more serious about it. Getting cut after the 3rd round of several-hour interviews at Google a year ago was a bit painful, but I was glad I went through that because it forced me to think about what I really wanted to do. It was actually the first time I interviewed for a job that I did not get. There would be a few others after that, but each bad interview taught me more and more about what I wanted.

Google came up because of a conversation with a friend at a ski house in France last year. It wasn’t exactly what I wanted, but hey, it was Google. Another company came up because of a well timed LinkedIn email just as the Google opportunity died (turned out they wanted a well-experienced do-it-all trainer but wanted to pay a fresh-out-of-college salary). And then I stopped pursuing anything for a good 6-9 months. That happened to coincide with the work I was doing to create FaxDocs.tv: I was having too much fun in my job to think about changing things.

So in March I decided to start looking again and thats when I put the Internet to work for me. The key tool I used to get me my job was IFTTT. Don’t try to pronounce it. Its “If This Then That”, or http://ifttt.com. IFTTT basically waits for something to happen on the internet and then does something in response. What kinds of things? Well, I use it to check tomorrows weather, check web sites without RSS, archive my Instagram pictures, auto-respond to new Twitter followers, and more.

But for job searching, I had IFTTT start searching a few sites every day and send me an email when it found a match. Each This and That combo is called a Recipe, and I had about 10-15 recipes for different sites and searches. I had searches on Craigslists for Seattle, San Francisco, Austin, NYC, and Boston for jobs with the word “evangelist” in them. I had searches on the various VC company pages for jobs at the companies they were funding, again looking for the evangelist role.

Every day, 3-10 jobs came into my inbox. Some were repeats, and some were actually jobs for pastors and preachers. But some looked like amazingly cool opportunities that I had to investigate. In April, I sent in my resume to one of those companies. Later that month we were talking (while I was in Sydney and Bangkok and San Antonio) on the phone and for some in-person interviews in Boston. In May came the offer, and next week I start the job: Technical Evangelist at a very cool web startup in Boston, Massachusetts.

Looking back at the interviews that did not work out, none of them were jobs that I really wanted. Some were startups a little too new (and risky) or too established (and rigid), some were Dev Evangelists, some were trainers. None of those were what I really wanted. Maybe that showed in the interviews because I wasn’t as excited as I should have been. One insisted on a Skype interview even though he had a terrible connection then had HR contact me to say I didn’t have the skills. If that was really it, they could have figured it out from my blog and twitter. (HINT: if you are hiring, have a bad internet connection and want to do a good interview, pick up the damned phone!). Glad I didn’t end up working for that guy.

Out of all the jobs I looked into there were many I was a perfect fit for, but there was only one that was a perfect fit for what I wanted to do right now. That was the one I was super excited about. That was the one I contacted several times mid-interview process and post-interview with ideas of what I would do in the role. I even made a video or two demonstrating my skills with their messaging. The one I was super excited about is exactly the one that I got. I can’t wait to get started!