<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/stylesheets/rss.css" type="text/css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>OnRails.org: Namespaces and Rake Command Completion</title>
    <link>http://onrails.org/articles/2006/08/30/namespaces-and-rake-command-completion</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Ruby On Rails and related matters.</description>
    <item>
      <title>Namespaces and Rake Command Completion</title>
      <description>&lt;strong&gt;Update:&lt;/strong&gt; &lt;a href="http://onrails.org/articles/2006/11/17/rake-command-completion-using-rake"&gt;Now using rake and caching&lt;/a&gt;

&lt;p&gt;I got some basic rake command line completion working today using Jon Baer&amp;#8217;s &lt;a href="http://weblog.rubyonrails.org/2006/3/9/fast-rake-task-completion-for-zsh#comment-2361"&gt;comment&lt;/a&gt;.  Very simple, very easy:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&lt;notextile&gt;complete -W '`rake—silent—tasks | cut -d ” ” -f 2`' -o default rake&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;However this didn&amp;#8217;t work for the namespaced tasks in a rails app like &lt;code&gt;rake test:units&lt;/code&gt;.  Searching a little further I found a reference to some code &lt;a href="http://i.conio.net/rake-completion.rb"&gt;Nicholas Seckar&lt;/a&gt; wrote on &lt;a href="http://project.ioni.st/post/212"&gt;project.ioni.st&lt;/a&gt;.  This used ruby to find the possible tasks for command completion.  This looked promising, but it still didn&amp;#8217;t work for namespaced tasks.  A little more googling led me to what looked like the perfect link: &lt;a href="http://www.webtypes.com/2006/03/31/rake-completion-script-that-handles-namespaces"&gt;Rake-completion script that handles namespaces&lt;/a&gt;.  Alas, it only handled one level of namespacing.  It worked nicely for &lt;code&gt;rake test:units&lt;/code&gt;, but &lt;code&gt;rake tmp:ses&amp;lt;TAB&amp;gt;&lt;/code&gt; would complete to &lt;code&gt;rake tmp:clear&lt;/code&gt; instead of &lt;code&gt;rake tmp:sessions:clear&lt;/code&gt;.  Also, &lt;code&gt;rake test:units &amp;lt;TAB&amp;gt;&lt;/code&gt; would complete to &lt;code&gt;rake test:units units&lt;/code&gt; instead of giving me all the tasks again, just in case you want to run multiple tasks form the command line.&lt;/p&gt;


	&lt;p&gt;So, now what?  Stand on the shoulders of others, naturally.  Here is what I&amp;#8217;m using now that handles multiple namespaces and multiple tasks per command line:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;notextile&gt;&lt;span class="comment"&gt;#!/usr/bin/env ruby&lt;/span&gt;

&lt;span class="comment"&gt;# Complete rake tasks script for bash&lt;/span&gt;
&lt;span class="comment"&gt;# Save it somewhere and then add&lt;/span&gt;
&lt;span class="comment"&gt;# complete -C path/to/script -o default rake&lt;/span&gt;
&lt;span class="comment"&gt;# to your ~/.bashrc&lt;/span&gt;
&lt;span class="comment"&gt;# Nicholas Seckar &amp;lt;nseckar@gmail.com&amp;gt;&lt;/span&gt;
&lt;span class="comment"&gt;# Saimon Moore &amp;lt;saimon@webtypes.com&amp;gt;&lt;/span&gt;
&lt;span class="comment"&gt;# http://www.webtypes.com/2006/03/31/rake-completion-script-that-handles-namespaces&lt;/span&gt;

&lt;span class="ident"&gt;exit&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;file?&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;Dir&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;pwd&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;Rakefile&lt;/span&gt;&lt;span class="punct"&gt;'))&lt;/span&gt;
&lt;span class="ident"&gt;exit&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt; &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;^rake&lt;span class="escape"&gt;\b&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="punct"&gt;=~&lt;/span&gt; &lt;span class="constant"&gt;ENV&lt;/span&gt;&lt;span class="punct"&gt;[&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;COMP_LINE&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;]&lt;/span&gt;

&lt;span class="ident"&gt;after_match&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="global"&gt;$'&lt;/span&gt;
&lt;span class="ident"&gt;task_match&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;after_match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;empty?&lt;/span&gt; &lt;span class="punct"&gt;||&lt;/span&gt; &lt;span class="ident"&gt;after_match&lt;/span&gt; &lt;span class="punct"&gt;=~&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;&lt;span class="escape"&gt;\s&lt;/span&gt;$&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="constant"&gt;nil&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;after_match&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;last&lt;/span&gt;
&lt;span class="ident"&gt;tasks&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; `&lt;span class="ident"&gt;rake&lt;/span&gt; &lt;span class="punct"&gt;--&lt;/span&gt;&lt;span class="ident"&gt;silent&lt;/span&gt; &lt;span class="punct"&gt;--&lt;/span&gt;&lt;span class="ident"&gt;tasks`&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="escape"&gt;\n&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;..-&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;].&lt;/span&gt;&lt;span class="ident"&gt;collect&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;line&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;line&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;split&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="number"&gt;1&lt;/span&gt;&lt;span class="punct"&gt;]}&lt;/span&gt;
&lt;span class="ident"&gt;tasks&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;tasks&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;select&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;^&lt;span class="expr"&gt;#{Regexp.escape task_match}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt; &lt;span class="punct"&gt;=~&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;}&lt;/span&gt; &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;task_match&lt;/span&gt;

&lt;span class="comment"&gt;# handle namespaces&lt;/span&gt;
&lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;task_match&lt;/span&gt; &lt;span class="punct"&gt;=~&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;^([-&lt;span class="escape"&gt;\w&lt;/span&gt;:]+:)&lt;/span&gt;&lt;span class="punct"&gt;/&lt;/span&gt;
  &lt;span class="ident"&gt;upto_last_colon&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="global"&gt;$1&lt;/span&gt;
  &lt;span class="ident"&gt;after_match&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="global"&gt;$'&lt;/span&gt;
  &lt;span class="ident"&gt;tasks&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;tasks&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;collect&lt;/span&gt; &lt;span class="punct"&gt;{&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="punct"&gt;=~&lt;/span&gt; &lt;span class="punct"&gt;/&lt;/span&gt;&lt;span class="regex"&gt;^&lt;span class="expr"&gt;#{Regexp.escape upto_last_colon}&lt;/span&gt;([-&lt;span class="escape"&gt;\w&lt;/span&gt;:]+)$&lt;/span&gt;&lt;span class="punct"&gt;/)&lt;/span&gt; &lt;span class="punct"&gt;?&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{$1}&lt;/span&gt;&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;:&lt;/span&gt; &lt;span class="ident"&gt;t&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="ident"&gt;puts&lt;/span&gt; &lt;span class="ident"&gt;tasks&lt;/span&gt;
&lt;span class="ident"&gt;exit&lt;/span&gt; &lt;span class="number"&gt;0&lt;/span&gt;&lt;/notextile&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;&lt;a href="http://onrails.org/files/rake-completion.rb"&gt;Enjoy&lt;/a&gt;&lt;/p&gt;
</description>
      <pubDate>Wed, 30 Aug 2006 21:34:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:4d2a935a-f730-406d-91af-b905e3b875cc</guid>
      <author>Lee Marlow</author>
      <link>http://onrails.org/articles/2006/08/30/namespaces-and-rake-command-completion</link>
      <category>Ruby</category>
      <category>Rails Tips</category>
      <category>Ruby On Rails</category>
    </item>
    <item>
      <title>"Namespaces and Rake Command Completion" by Nikos D.</title>
      <description>Hmm&amp;#8230; I think I found a bug.
In line 16 you say :
&lt;pre&gt;
tasks = rake_silent_tasks.split("\n")[1..-1].map { |line| line.split[1] }
&lt;/pre&gt;

I guess that you DO want the first result to show up, so what you want is :
&lt;pre&gt;
tasks = rake_silent_tasks.split("\n")[0..-1].map { |line| line.split[1] }
&lt;/pre&gt;

	&lt;p&gt;Cheers! Really handy script :)&lt;/p&gt;</description>
      <pubDate>Thu, 17 Apr 2008 13:55:36 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:a734ad04-6ca4-4b83-b781-0910e4466ebc</guid>
      <link>http://onrails.org/articles/2006/08/30/namespaces-and-rake-command-completion#comment-3473</link>
    </item>
    <item>
      <title>"Namespaces and Rake Command Completion" by Saimon Moore</title>
      <description>&lt;p&gt;Hi Lee,&lt;/p&gt;


	&lt;p&gt;Great improvement on the script. A lot quicker as well. Thanks.&lt;/p&gt;


	&lt;p&gt;I&amp;#8217;ve updated my entry to point people to your version.&lt;/p&gt;</description>
      <pubDate>Fri, 22 Sep 2006 07:54:17 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:6a7ba06b-cc9d-43bf-87ae-1aaae1894b49</guid>
      <link>http://onrails.org/articles/2006/08/30/namespaces-and-rake-command-completion#comment-154</link>
    </item>
  </channel>
</rss>
