Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Adding post: TextMate, Rspec and Dot Spec Party.

  • Loading branch information...
commit da90df5de3dd6c536c88321af51a66d637389d49 1 parent f2e09c4
@jqr authored
View
80 _posts/2009-02-06-textmate-rspec-and-dot-spec-party.textile
@@ -0,0 +1,80 @@
+---
+layout: post
+title: TextMate, Rspec and Dot Spec Party
+---
+
+I'm going to show you how to get a great looking RSpec runner window and not go insane while trying to use it.
+
+<img src="/images/posts/rspec_runner.jpg" />
+
+Beautiful passing green specs, easy to read failing red specs, a clickable backtrace and the failing spec for good measure.
+
+Pretty sweet right? Let me show you how to get started.
+
+<h3>Install RSpec bundle</h3>
+
+{% highlight sh %}
+mkdir -p ~/Library/Application\ Support/TextMate/Bundles/
+cd ~/Library/Application\ Support/TextMate/Bundles/
+git clone git://github.com/dchelimsky/rspec-tmbundle.git RSpec.tmbundle
+osascript -e 'tell app "TextMate" to reload bundles'
+{% endhighlight %}
+
+<h3>And now the fun begins</h3>
+
+<ol>
+ <li>First you press Shift-Control-Option R (⇧⌃⌥R) to select the RSpec Bundle. This is so easy it only takes two hands.
+ <img src="/images/posts/shift_control_option_r.jpg"></li>
+ <li>Now we need to press Command 3 (⌘3) to select the RSpec Bundle out of the list.
+ <img src="/images/posts/mode_select_r.png" /></li>
+ <li>Command R (⌘R) to run the spec or Shift Command R (⇧⌘R) to run an individual spec.</li>
+ <li>Party time!</li>
+</ol>
+
+<h3>The party's over</h3>
+
+The next time you open a spec or regular Ruby file you'll be started in the mode you last forced. That means you'll probably have to learn to do that tedious keyboard finger dance quite often.
+
+<script type="text/javascript" src="/javascripts/audio-player.js"></script>
+<script type="text/javascript">
+ AudioPlayer.setup("/media/player.swf", {
+ width: 290
+ });
+</script>
+
+<p class="audio" id="obama_complicated">[Audio] "This shit's getting way too complicated for me." - Barack Obama</p>
+<script type="text/javascript">
+ AudioPlayer.embed("obama_complicated", {soundFile: "/media/obama_complicated.mp3"});
+</script>
+
+
+We could switch the Ruby and RSpec shortcuts to a simpler keystroke, that would alleviate most of the problem. Except we would still need to press some keystroke to force the mode upon opening a new file.
+
+Running specs needs to be dead simple so people actually do it!
+
+<h3>Dot spec has invited you to a party!</h3>
+
+There's a far easier way to solve this problem. Just rename all your spec files to .spec and you will only have to tell TextMate one time to use RSpec mode and it will remember forever!
+
+The steps after switching to dot spec:
+
+<ol>
+ <li>Command R (⌘R) to run the spec or Shift Command R (⇧⌘R) to run an individual spec.</li>
+ <li>Party Time!
+ <img src="http://www.scienceyear.com/parents/party_time/images/party_time_top.gif" /></li>
+</ol>
+
+<h3>You've also been invited to a pre-party!</h3>
+
+Who has time to rename all those files? Definitely not you!
+
+If you act now, we'll throw in a <a href="http://github.com/jqr/thor_tasks/raw/master/rspec_rename_to_dotspec.thor">fancy converter</a> for all your old specs!
+
+
+{% highlight sh %}
+# in your project dir
+gem install thor &&
+thor install \
+http://github.com/jqr/thor_tasks/raw/master/rspec_rename_to_dotspec.thor &&
+thor rspec:rename_to_dotspec
+{% endhighlight %}
View
BIN  images/posts/mode_select_r.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/posts/rspec_runner.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
BIN  images/posts/shift_control_option_r.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
1  javascripts/audio-player-noswfobject.js
@@ -0,0 +1 @@
+var AudioPlayer=function(){var F=[];var C;var E="";var A={};var D=-1;function B(G){return document.all?window[G]:document[G]}return{setup:function(H,G){E=H;A=G},getPlayer:function(G){return B(G)},embed:function(K,O){var I={};var M;var G;var P;var H;var N={};var J={};var L={};for(M in A){I[M]=A[M]}for(M in O){I[M]=O[M]}if(I.transparentpagebg=="yes"){N.bgcolor="#FFFFFF";N.wmode="transparent"}else{if(I.pagebg){N.bgcolor="#"+I.pagebg}N.wmode="opaque"}N.menu="false";for(M in I){if(M=="pagebg"||M=="width"||M=="transparentpagebg"){continue}J[M]=I[M]}L.name=K;L.style="outline: none";J.playerID=K;audioplayer_swfobject.embedSWF(E,K,I.width.toString(),"24","9",false,J,N,L);F.push(K)},syncVolumes:function(G,I){D=I;for(var H=0;H<F.length;H++){if(F[H]!=G){B(F[H]).setVolume(D)}}},activate:function(G){if(C&&C!=G){B(C).close()}C=G},load:function(I,G,J,H){B(I).load(G,J,H)},close:function(G){B(G).close();if(G==C){C=null}},open:function(G){B(G).open()},getVolume:function(G){return D}}}()
View
109 javascripts/audio-player-uncompressed.js
@@ -0,0 +1,109 @@
+var AudioPlayer = function () {
+ var instances = [];
+ var activePlayerID;
+ var playerURL = "";
+ var defaultOptions = {};
+ var currentVolume = -1;
+
+ function getPlayer(playerID) {
+ return document.all ? window[playerID] : document[playerID];
+ }
+
+ return {
+ setup: function (url, options) {
+ playerURL = url;
+ defaultOptions = options;
+ },
+
+ getPlayer: function (playerID) {
+ return getPlayer(playerID);
+ },
+
+ embed: function (elementID, options) {
+ var instanceOptions = {};
+ var key;
+ var so;
+ var bgcolor;
+ var wmode;
+
+ var flashParams = {};
+ var flashVars = {};
+ var flashAttributes = {};
+
+ // Merge default options and instance options
+ for (key in defaultOptions) {
+ instanceOptions[key] = defaultOptions[key];
+ }
+ for (key in options) {
+ instanceOptions[key] = options[key];
+ }
+
+ if (instanceOptions.transparentpagebg == "yes") {
+ flashParams.bgcolor = "#FFFFFF";
+ flashParams.wmode = "transparent";
+ } else {
+ if (instanceOptions.pagebg) {
+ flashParams.bgcolor = "#" + instanceOptions.pagebg;
+ }
+ flashParams.wmode = "opaque";
+ }
+
+ flashParams.menu = "false";
+
+ for (key in instanceOptions) {
+ if (key == "pagebg" || key == "width" || key == "transparentpagebg") {
+ continue;
+ }
+ flashVars[key] = instanceOptions[key];
+ }
+
+ flashAttributes.name = elementID;
+ flashAttributes.style = "outline: none";
+
+ flashVars.playerID = elementID;
+
+ swfobject.embedSWF(playerURL, elementID, instanceOptions.width.toString(), "24", "9", false, flashVars, flashParams, flashAttributes);
+
+
+ instances.push(elementID);
+ },
+
+ syncVolumes: function (playerID, volume) {
+ currentVolume = volume;
+ for (var i = 0; i < instances.length; i++) {
+ if (instances[i] != playerID) {
+ getPlayer(instances[i]).setVolume(currentVolume);
+ }
+ }
+ },
+
+ activate: function (playerID) {
+ if (activePlayerID && activePlayerID != playerID) {
+ getPlayer(activePlayerID).close();
+ }
+
+ activePlayerID = playerID;
+ },
+
+ load: function (playerID, soundFile, titles, artists) {
+ getPlayer(playerID).load(soundFile, titles, artists);
+ },
+
+ close: function (playerID) {
+ getPlayer(playerID).close();
+ if (playerID == activePlayerID) {
+ activePlayerID = null;
+ }
+ },
+
+ open: function (playerID) {
+ getPlayer(playerID).open();
+ },
+
+ getVolume: function (playerID) {
+ return currentVolume;
+ }
+
+ }
+
+}();
View
5 javascripts/audio-player.js
@@ -0,0 +1,5 @@
+var AudioPlayer=function(){var F=[];var C;var E="";var A={};var D=-1;function B(G){return document.all?window[G]:document[G]}return{setup:function(H,G){E=H;A=G},getPlayer:function(G){return B(G)},embed:function(K,O){var I={};var M;var G;var P;var H;var N={};var J={};var L={};for(M in A){I[M]=A[M]}for(M in O){I[M]=O[M]}if(I.transparentpagebg=="yes"){N.bgcolor="#FFFFFF";N.wmode="transparent"}else{if(I.pagebg){N.bgcolor="#"+I.pagebg}N.wmode="opaque"}N.menu="false";for(M in I){if(M=="pagebg"||M=="width"||M=="transparentpagebg"){continue}J[M]=I[M]}L.name=K;L.style="outline: none";J.playerID=K;audioplayer_swfobject.embedSWF(E,K,I.width.toString(),"24","9",false,J,N,L);F.push(K)},syncVolumes:function(G,I){D=I;for(var H=0;H<F.length;H++){if(F[H]!=G){B(F[H]).setVolume(D)}}},activate:function(G){if(C&&C!=G){B(C).close()}C=G},load:function(I,G,J,H){B(I).load(G,J,H)},close:function(G){B(G).close();if(G==C){C=null}},open:function(G){B(G).open()},getVolume:function(G){return D}}}()/* SWFObject v2.1 <http://code.google.com/p/swfobject/>
+ Copyright (c) 2007-2008 Geoff Stearns, Michael Williams, and Bobby van der Sluis
+ This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
+*/
+var audioplayer_swfobject=function(){var b="undefined",Q="object",n="Shockwave Flash",p="ShockwaveFlash.ShockwaveFlash",P="application/x-shockwave-flash",m="SWFObjectExprInst",j=window,K=document,T=navigator,o=[],N=[],i=[],d=[],J,Z=null,M=null,l=null,e=false,A=false;var h=function(){var v=typeof K.getElementById!=b&&typeof K.getElementsByTagName!=b&&typeof K.createElement!=b,AC=[0,0,0],x=null;if(typeof T.plugins!=b&&typeof T.plugins[n]==Q){x=T.plugins[n].description;if(x&&!(typeof T.mimeTypes!=b&&T.mimeTypes[P]&&!T.mimeTypes[P].enabledPlugin)){x=x.replace(/^.*\s+(\S+\s+\S+$)/,"$1");AC[0]=parseInt(x.replace(/^(.*)\..*$/,"$1"),10);AC[1]=parseInt(x.replace(/^.*\.(.*)\s.*$/,"$1"),10);AC[2]=/r/.test(x)?parseInt(x.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof j.ActiveXObject!=b){var y=null,AB=false;try{y=new ActiveXObject(p+".7")}catch(t){try{y=new ActiveXObject(p+".6");AC=[6,0,21];y.AllowScriptAccess="always"}catch(t){if(AC[0]==6){AB=true}}if(!AB){try{y=new ActiveXObject(p)}catch(t){}}}if(!AB&&y){try{x=y.GetVariable("$version");if(x){x=x.split(" ")[1].split(",");AC=[parseInt(x[0],10),parseInt(x[1],10),parseInt(x[2],10)]}}catch(t){}}}}var AD=T.userAgent.toLowerCase(),r=T.platform.toLowerCase(),AA=/webkit/.test(AD)?parseFloat(AD.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,q=false,z=r?/win/.test(r):/win/.test(AD),w=r?/mac/.test(r):/mac/.test(AD);/*@cc_on q=true;@if(@_win32)z=true;@elif(@_mac)w=true;@end@*/return{w3cdom:v,pv:AC,webkit:AA,ie:q,win:z,mac:w}}();var L=function(){if(!h.w3cdom){return }f(H);if(h.ie&&h.win){try{K.write("<script id=__ie_ondomload defer=true src=//:><\/script>");J=C("__ie_ondomload");if(J){I(J,"onreadystatechange",S)}}catch(q){}}if(h.webkit&&typeof K.readyState!=b){Z=setInterval(function(){if(/loaded|complete/.test(K.readyState)){E()}},10)}if(typeof K.addEventListener!=b){K.addEventListener("DOMContentLoaded",E,null)}R(E)}();function S(){if(J.readyState=="complete"){J.parentNode.removeChild(J);E()}}function E(){if(e){return }if(h.ie&&h.win){var v=a("span");try{var u=K.getElementsByTagName("body")[0].appendChild(v);u.parentNode.removeChild(u)}catch(w){return }}e=true;if(Z){clearInterval(Z);Z=null}var q=o.length;for(var r=0;r<q;r++){o[r]()}}function f(q){if(e){q()}else{o[o.length]=q}}function R(r){if(typeof j.addEventListener!=b){j.addEventListener("load",r,false)}else{if(typeof K.addEventListener!=b){K.addEventListener("load",r,false)}else{if(typeof j.attachEvent!=b){I(j,"onload",r)}else{if(typeof j.onload=="function"){var q=j.onload;j.onload=function(){q();r()}}else{j.onload=r}}}}}function H(){var t=N.length;for(var q=0;q<t;q++){var u=N[q].id;if(h.pv[0]>0){var r=C(u);if(r){N[q].width=r.getAttribute("width")?r.getAttribute("width"):"0";N[q].height=r.getAttribute("height")?r.getAttribute("height"):"0";if(c(N[q].swfVersion)){if(h.webkit&&h.webkit<312){Y(r)}W(u,true)}else{if(N[q].expressInstall&&!A&&c("6.0.65")&&(h.win||h.mac)){k(N[q])}else{O(r)}}}}else{W(u,true)}}}function Y(t){var q=t.getElementsByTagName(Q)[0];if(q){var w=a("embed"),y=q.attributes;if(y){var v=y.length;for(var u=0;u<v;u++){if(y[u].nodeName=="DATA"){w.setAttribute("src",y[u].nodeValue)}else{w.setAttribute(y[u].nodeName,y[u].nodeValue)}}}var x=q.childNodes;if(x){var z=x.length;for(var r=0;r<z;r++){if(x[r].nodeType==1&&x[r].nodeName=="PARAM"){w.setAttribute(x[r].getAttribute("name"),x[r].getAttribute("value"))}}}t.parentNode.replaceChild(w,t)}}function k(w){A=true;var u=C(w.id);if(u){if(w.altContentId){var y=C(w.altContentId);if(y){M=y;l=w.altContentId}}else{M=G(u)}if(!(/%$/.test(w.width))&&parseInt(w.width,10)<310){w.width="310"}if(!(/%$/.test(w.height))&&parseInt(w.height,10)<137){w.height="137"}K.title=K.title.slice(0,47)+" - Flash Player Installation";var z=h.ie&&h.win?"ActiveX":"PlugIn",q=K.title,r="MMredirectURL="+j.location+"&MMplayerType="+z+"&MMdoctitle="+q,x=w.id;if(h.ie&&h.win&&u.readyState!=4){var t=a("div");x+="SWFObjectNew";t.setAttribute("id",x);u.parentNode.insertBefore(t,u);u.style.display="none";var v=function(){u.parentNode.removeChild(u)};I(j,"onload",v)}U({data:w.expressInstall,id:m,width:w.width,height:w.height},{flashvars:r},x)}}function O(t){if(h.ie&&h.win&&t.readyState!=4){var r=a("div");t.parentNode.insertBefore(r,t);r.parentNode.replaceChild(G(t),r);t.style.display="none";var q=function(){t.parentNode.removeChild(t)};I(j,"onload",q)}else{t.parentNode.replaceChild(G(t),t)}}function G(v){var u=a("div");if(h.win&&h.ie){u.innerHTML=v.innerHTML}else{var r=v.getElementsByTagName(Q)[0];if(r){var w=r.childNodes;if(w){var q=w.length;for(var t=0;t<q;t++){if(!(w[t].nodeType==1&&w[t].nodeName=="PARAM")&&!(w[t].nodeType==8)){u.appendChild(w[t].cloneNode(true))}}}}}return u}function U(AG,AE,t){var q,v=C(t);if(v){if(typeof AG.id==b){AG.id=t}if(h.ie&&h.win){var AF="";for(var AB in AG){if(AG[AB]!=Object.prototype[AB]){if(AB.toLowerCase()=="data"){AE.movie=AG[AB]}else{if(AB.toLowerCase()=="styleclass"){AF+=' class="'+AG[AB]+'"'}else{if(AB.toLowerCase()!="classid"){AF+=" "+AB+'="'+AG[AB]+'"'}}}}}var AD="";for(var AA in AE){if(AE[AA]!=Object.prototype[AA]){AD+='<param name="'+AA+'" value="'+AE[AA]+'" />'}}v.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AF+">"+AD+"</object>";i[i.length]=AG.id;q=C(AG.id)}else{if(h.webkit&&h.webkit<312){var AC=a("embed");AC.setAttribute("type",P);for(var z in AG){if(AG[z]!=Object.prototype[z]){if(z.toLowerCase()=="data"){AC.setAttribute("src",AG[z])}else{if(z.toLowerCase()=="styleclass"){AC.setAttribute("class",AG[z])}else{if(z.toLowerCase()!="classid"){AC.setAttribute(z,AG[z])}}}}}for(var y in AE){if(AE[y]!=Object.prototype[y]){if(y.toLowerCase()!="movie"){AC.setAttribute(y,AE[y])}}}v.parentNode.replaceChild(AC,v);q=AC}else{var u=a(Q);u.setAttribute("type",P);for(var x in AG){if(AG[x]!=Object.prototype[x]){if(x.toLowerCase()=="styleclass"){u.setAttribute("class",AG[x])}else{if(x.toLowerCase()!="classid"){u.setAttribute(x,AG[x])}}}}for(var w in AE){if(AE[w]!=Object.prototype[w]&&w.toLowerCase()!="movie"){F(u,w,AE[w])}}v.parentNode.replaceChild(u,v);q=u}}}return q}function F(t,q,r){var u=a("param");u.setAttribute("name",q);u.setAttribute("value",r);t.appendChild(u)}function X(r){var q=C(r);if(q&&(q.nodeName=="OBJECT"||q.nodeName=="EMBED")){if(h.ie&&h.win){if(q.readyState==4){B(r)}else{j.attachEvent("onload",function(){B(r)})}}else{q.parentNode.removeChild(q)}}}function B(t){var r=C(t);if(r){for(var q in r){if(typeof r[q]=="function"){r[q]=null}}r.parentNode.removeChild(r)}}function C(t){var q=null;try{q=K.getElementById(t)}catch(r){}return q}function a(q){return K.createElement(q)}function I(t,q,r){t.attachEvent(q,r);d[d.length]=[t,q,r]}function c(t){var r=h.pv,q=t.split(".");q[0]=parseInt(q[0],10);q[1]=parseInt(q[1],10)||0;q[2]=parseInt(q[2],10)||0;return(r[0]>q[0]||(r[0]==q[0]&&r[1]>q[1])||(r[0]==q[0]&&r[1]==q[1]&&r[2]>=q[2]))?true:false}function V(v,r){if(h.ie&&h.mac){return }var u=K.getElementsByTagName("head")[0],t=a("style");t.setAttribute("type","text/css");t.setAttribute("media","screen");if(!(h.ie&&h.win)&&typeof K.createTextNode!=b){t.appendChild(K.createTextNode(v+" {"+r+"}"))}u.appendChild(t);if(h.ie&&h.win&&typeof K.styleSheets!=b&&K.styleSheets.length>0){var q=K.styleSheets[K.styleSheets.length-1];if(typeof q.addRule==Q){q.addRule(v,r)}}}function W(t,q){var r=q?"visible":"hidden";if(e&&C(t)){C(t).style.visibility=r}else{V("#"+t,"visibility:"+r)}}function g(s){var r=/[\\\"<>\.;]/;var q=r.exec(s)!=null;return q?encodeURIComponent(s):s}var D=function(){if(h.ie&&h.win){window.attachEvent("onunload",function(){var w=d.length;for(var v=0;v<w;v++){d[v][0].detachEvent(d[v][1],d[v][2])}var t=i.length;for(var u=0;u<t;u++){X(i[u])}for(var r in h){h[r]=null}h=null;for(var q in audioplayer_swfobject){audioplayer_swfobject[q]=null}audioplayer_swfobject=null})}}();return{registerObject:function(u,q,t){if(!h.w3cdom||!u||!q){return }var r={};r.id=u;r.swfVersion=q;r.expressInstall=t?t:false;N[N.length]=r;W(u,false)},getObjectById:function(v){var q=null;if(h.w3cdom){var t=C(v);if(t){var u=t.getElementsByTagName(Q)[0];if(!u||(u&&typeof t.SetVariable!=b)){q=t}else{if(typeof u.SetVariable!=b){q=u}}}}return q},embedSWF:function(x,AE,AB,AD,q,w,r,z,AC){if(!h.w3cdom||!x||!AE||!AB||!AD||!q){return }AB+="";AD+="";if(c(q)){W(AE,false);var AA={};if(AC&&typeof AC===Q){for(var v in AC){if(AC[v]!=Object.prototype[v]){AA[v]=AC[v]}}}AA.data=x;AA.width=AB;AA.height=AD;var y={};if(z&&typeof z===Q){for(var u in z){if(z[u]!=Object.prototype[u]){y[u]=z[u]}}}if(r&&typeof r===Q){for(var t in r){if(r[t]!=Object.prototype[t]){if(typeof y.flashvars!=b){y.flashvars+="&"+t+"="+r[t]}else{y.flashvars=t+"="+r[t]}}}}f(function(){U(AA,y,AE);if(AA.id==AE){W(AE,true)}})}else{if(w&&!A&&c("6.0.65")&&(h.win||h.mac)){A=true;W(AE,false);f(function(){var AF={};AF.id=AF.altContentId=AE;AF.width=AB;AF.height=AD;AF.expressInstall=w;k(AF)})}}},getFlashPlayerVersion:function(){return{major:h.pv[0],minor:h.pv[1],release:h.pv[2]}},hasFlashPlayerVersion:c,createSWF:function(t,r,q){if(h.w3cdom){return U(t,r,q)}else{return undefined}},removeSWF:function(q){if(h.w3cdom){X(q)}},createCSS:function(r,q){if(h.w3cdom){V(r,q)}},addDomLoadEvent:f,addLoadEvent:R,getQueryParamValue:function(v){var u=K.location.search||K.location.hash;if(v==null){return g(u)}if(u){var t=u.substring(1).split("&");for(var r=0;r<t.length;r++){if(t[r].substring(0,t[r].indexOf("="))==v){return g(t[r].substring((t[r].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(A&&M){var q=C(m);if(q){q.parentNode.replaceChild(M,q);if(l){W(l,true);if(h.ie&&h.win){M.style.display="block"}}M=null;l=null;A=false}}}}}();
View
BIN  media/obama_complicated.mp3
Binary file not shown
View
BIN  media/player.swf
Binary file not shown
Please sign in to comment.
Something went wrong with that request. Please try again.