<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en">
<head>
  <title>the all-thing</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <link rel="stylesheet" href="/static/style.css" type="text/css" />
  <link rel="alternate" type="application/rss+xml" title="the all-thing RSS feed" href="/index.rss" />
  <link rel="alternate" type="text/plain" title="the all-thing in plain text" href="/index.txt" />
  <script type="text/javascript" src="/static/mootools.js"></script>
  <script type="text/javascript" src="http://music.masanjin.net:9292/waxiest.js"></script>
</head>
<body>

<div id="main">
  <div id="header">
    <h1><a  href="/">the all-thing</a></h1>
    
      <p>Showing only posts labeled "ditz" (<a  href="/label/ditz.rss">rss</a>). <a  href="/index/">See all posts</a>.</p>
    
  </div>
  <div id="sidebar">
    <h3>Recent comments</h3>

    <ul class="sidebar-list">
    
    <li><b><a  href="/whisper-0.5#58174069c046a78e55f02ef81da81e74">Dominique Julia</a></b>
        <i><a  href="/whisper-0.5">Whisper 0.5 released</a></i>
           one week ago
    </li>
    
    <li><b><a  href="/ruby-ncurses-and-thread-blocking#8fa2a0f392d7c0562d630e4936407c11">William Morgan</a></b>
        <i><a  href="/ruby-ncurses-and-thread-blocking">Ruby, Ncurses and blocked threads</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/git-wtf-bf06ab7-released#533654a7a229569e27a6d0afd716c444">William Morgan</a></b>
        <i><a  href="/git-wtf-bf06ab7-released">git wtf bf06ab7 released</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/git-wtf-bf06ab7-released#b7b7a905477674eb6985b34a964a0dca">Joao Nelas</a></b>
        <i><a  href="/git-wtf-bf06ab7-released">git wtf bf06ab7 released</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/ruby-ncurses-and-thread-blocking#b00001114360ac152f87d4ac2a6e0c5b">Ollivier Robert</a></b>
        <i><a  href="/ruby-ncurses-and-thread-blocking">Ruby, Ncurses and blocked threads</a></i>
           three months ago
    </li>
    
    </ul>

    <h3>Authors</h3>
    <ul class="sidebar-list">
    
      <li><a class="author" href="/by/William+Morgan/">William&nbsp;Morgan</a>&nbsp;(65) </li>
    
    </ul>

    <h3>Tags</h3>
    <ul class="sidebar-list">
    
      <li><a class="label" href="/label/releases/">releases</a>&nbsp;(15) </li>
    
      <li><a class="label" href="/label/whisper/">whisper</a>&nbsp;(13) </li>
    
      <li><a class="label" href="/label/git/">git</a>&nbsp;(9) </li>
    
      <li><a class="label" href="/label/stats/">stats</a>&nbsp;(8) </li>
    
      <li><a class="label" href="/label/trollop/">trollop</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/ruby/">ruby</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/sup/">sup</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/git-wtf/">git-wtf</a>&nbsp;(4) </li>
    
      <li><a class="label" href="/label/vm/">vm</a>&nbsp;(4) </li>
    
      <li><a class="label" href="/label/mathml/">mathml</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/continuations/">continuations</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/ditz/">ditz</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/proglang/">proglang</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/optimization/">optimization</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/benchmarks/">benchmarks</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/rubinius/">rubinius</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/inlining/">inlining</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ubuntu/">ubuntu</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/fibers/">fibers</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ritex/">ritex</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ruby1.9/">ruby1.9</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ncurses/">ncurses</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/javascript/">javascript</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/media/">media</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/vim/">vim</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/classification/">classification</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/massachusetts/">massachusetts</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/greasemonkey/">greasemonkey</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/wine/">wine</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/readme/">readme</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/ancient-greek/">ancient-greek</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/web/">web</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/current+events/">current&nbsp;events</a>&nbsp;(1) </li>
    
    </ul>

    <h3>Other formats</h3>
    <ul class="sidebar-list">
    <li><a href="/index.rss"><img src="/static/rss-badge.png"/></a></li>
    <li><a href="/index.txt">plain text version</a></li>
    </ul>

    <h3 class="waxiest.author.original">Who is this man?</h3>
    <h3 class="waxiest.author.beautiful" style="display:none">I must find out more about this beautiful creature</h3>
    <h3 class="waxiest.author.beautifulbig" style="display:none">I MUST FIND OUT MORE ABOUT THIS BEAUTIFUL CREATURE</h3>
    <h3 class="waxiest.author.originalbig" style="display:none">WHO IS THIS MAN?</h3>

    <script type="text/javascript">
      var w = waxiest();
      w.optimizeHTMLSection("author", ["original", "beautiful", "beautifulbig", "originalbig"]);
    </script>

    <a href="http://masanjin.net" onClick="w.goalReached('greeting')">William Morgan</a>
  </div>
  <div id="content">
    
  <h2><a  href="/old14">Google textfile auto-titleing</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="19 months ago">July 28, 2008  2:25pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/ditz/">ditz</a></span> </div>
  
  <p class='first'>If you search for &#8220;ditz readme&#8221; on the Googles, the <a href="http://ditz.rubyforge.org/README.txt">correct result</a>, which is a text file and not an <span class="caps">HTML</span> page, appears with the title &#8220;DitzのREADME&#8221;. This is probably because there&#8217;s a link to it titled as such in this <a href="http://d.hatena.ne.jp/antipop/20080412/1208010913">Japanese description of a Ditz emacs mode</a>. Apparently Google prefers that title over the link just called &#8220;<span class="caps">README</span>&#8221; on the the Ditz main page.</p>
  <div class="comment-link">
    
    <a  href="/old14#comments">No comments</a>.
  </div>

  <h2><a  href="/old26">Ditz 0.4, and the magic of Ruby DSLs</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="19 months ago">July 27, 2008  6:21pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/ditz/">ditz</a></span> </div>
  
  <p class='first'>I&#8217;ve just released Ditz 0.4. The big-ticket item in this release is the plugin
system, which makes it very easy to tweak Ditz&#8217;s models, views and controllers.
There&#8217;s an included git plugin which does some nice things like linking git
commits and git branches to individual Ditz issues.</p>
<p>The new bash completion is pretty nice too. The completion code has been
reworked a bit and now ties in very nicely with the argument processing. Check
out this code from the Ditz&#8217;s controller
(<a href="http://gitorious.org/projects/ditz/repos/mainline/blobs/master/lib%2Foperator.rb">operator.rb</a>,
for those following along from your repo):</p>
<p><code><pre class="ruby"><span class="ident">operation</span> <span class="symbol">:start</span><span class="punct">,</span> <span class="punct">&quot;</span><span class="string">Start work on an issue</span><span class="punct">&quot;,</span> <span class="symbol">:unstarted_issue</span>
<span class="keyword">def </span><span class="method">start</span> <span class="ident">project</span><span class="punct">,</span> <span class="ident">config</span><span class="punct">,</span> <span class="ident">issue</span>
  <span class="comment">## ...</span>
<span class="keyword">end</span></pre></code></p>
<p>Just by calling the operation method, we get:</p>
<ul>
	<li>Argument checking. There must be one argument to &#8216;ditz start&#8217;, and it must be
an unstarted issue. Any violations are handled nicely for us without having
to invoke the method.</li>
	<li>Help messages in &#8216;ditz help&#8217; and &#8216;ditz help start&#8217;.</li>
	<li>Argument completion. Running &#8217;ditz start &#8217; outputs a list of
possible completions for a command (in this case, all unstarted issues) and
then exits. Shell completion scripts can parse this output and present it to
you when you hit tab.</li>
</ul>
<p>So that&#8217;s a little <span class="caps">DSL</span> that I think turned out well.</p>
<p>Writing a plugin is also nicely DSLified. Here are some examples from plugin/git.rb:</p>
<p><code><pre class="ruby"><span class="keyword">class </span><span class="class">Issue</span>
 <span class="ident">field</span> <span class="symbol">:git_branch</span><span class="punct">,</span> <span class="symbol">:ask</span> <span class="punct">=&gt;</span> <span class="constant">false</span>

 <span class="keyword">def </span><span class="method">git_commits</span>
   <span class="comment">## ...</span>
 <span class="keyword">end</span>
<span class="keyword">end</span></pre></code></p>
<p>Here we reopen the Issue class and add a field called
<code>git_branch</code>, and we specify that the UI shouldn&#8217;t ask for this
field when an issue is created, since I decided that would be too annoying.
(We&#8217;ll see how we allow the user to explicitly set it below.) We also add a
method that&#8217;s responsible for actually getting the commits out of git.</p>
<p>Since our configuration file is just a Ditz model object, we can do the same
thing to add the configuration parameters we need:</p>
<p><code><pre class="ruby"><span class="keyword">class </span><span class="class">Config</span>
  <span class="ident">field</span> <span class="symbol">:git_commit_url_prefix</span><span class="punct">,</span>
    <span class="symbol">:prompt</span> <span class="punct">=&gt;&quot;</span><span class="string">URL prefix (if any) to link git commits to</span><span class="punct">&quot;</span>
  <span class="ident">field</span> <span class="symbol">:git_branch_url_prefix</span><span class="punct">,</span>
    <span class="symbol">:prompt</span> <span class="punct">=&gt;</span> <span class="punct">&quot;</span><span class="string">URL prefix (if any) to link git branches to</span><span class="punct">&quot;</span>
<span class="keyword">end</span></pre></code></p>
<p>We&#8217;ll use those two fields to add some links when we generate <span class="caps">HTML</span>.</p>
<p>Adding commands to Ditz&#8217;s controller is just as easy. Just reopen the class:</p>
<p><code><pre class="ruby"><span class="keyword">class </span><span class="class">Operator</span>
 <span class="ident">operation</span> <span class="symbol">:set_branch</span><span class="punct">,</span> <span class="punct">&quot;</span><span class="string">Set the git feature branch of an issue</span><span class="punct">&quot;,</span>
           <span class="symbol">:issue</span><span class="punct">,</span> <span class="symbol">:maybe_string</span>
 <span class="keyword">def </span><span class="method">set_branch</span> <span class="ident">project</span><span class="punct">,</span> <span class="ident">config</span><span class="punct">,</span> <span class="ident">issue</span><span class="punct">,</span> <span class="ident">maybe_string</span>
   <span class="comment">## ...</span>
 <span class="keyword">end</span>
<span class="keyword">end</span></pre></code></p>
<p>So now we have a <code>set-branch</code> command that takes an issue name, and
an optional branch name. And it&#8217;s a first-class citizen alongside every other
command: shows up in the help page, has argument auto-completion, etc.</p>
<p>Finally, let&#8217;s see how we modify the views. One thing we&#8217;d like to see is the
git branch for an issue, if it&#8217;s been set.</p>
<p><code><pre class="ruby"><span class="keyword">class </span><span class="class">ScreenView</span>
 <span class="ident">add_to_view</span> <span class="symbol">:issue_summary</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">issue</span><span class="punct">,</span> <span class="ident">config</span><span class="punct">|</span>
   <span class="punct">&quot;</span><span class="string"> Git branch: <span class="expr">#{issue.git_branch || 'none'}</span><span class="escape">\n</span></span><span class="punct">&quot;</span>
 <span class="keyword">end</span>
<span class="keyword">end</span></pre></code></p>
<p>Here we&#8217;ve opened up the ScreenView class (which is used for generating the
screen output, as opposed to the <span class="caps">HTML</span> output) and added a closure to the
summary section, which prints out the value of the model field we added above.
The <span class="caps">HTML</span> version is similar:</p>
<p><code><pre class="ruby"><span class="keyword">class </span><span class="class">HtmlView</span>
  <span class="ident">add_to_view</span> <span class="symbol">:issue_summary</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">issue</span><span class="punct">,</span> <span class="ident">config</span><span class="punct">|</span>
    <span class="keyword">next</span> <span class="keyword">unless</span> <span class="ident">issue</span><span class="punct">.</span><span class="ident">git_branch</span>
    <span class="punct">[{</span> <span class="symbol">:issue</span> <span class="punct">=&gt;</span> <span class="ident">issue</span><span class="punct">,</span>
       <span class="symbol">:url_prefix</span> <span class="punct">=&gt;</span> <span class="ident">config</span><span class="punct">.</span><span class="ident">git_branch_url_prefix</span> <span class="punct">},</span> <span class="punct">&lt;&lt;</span><span class="constant">EOS</span><span class="punct">]</span><span class="string">
  Git branch:
&lt;tr&gt;
  &lt;td class='attrname'&gt;Git branch:&lt;/td&gt;
  &lt;td class='attrval'&gt;
    &lt;%= url_prefix ?
      link_to([url_prefix, issue.git_branch].join,
        issue.git_branch) :
      h(issue.git_branch) %&gt;
  &lt;/td&gt;
&lt;/tr&gt;
</span><span class="constant">EOS</span>
  <span class="keyword">end</span>
<span class="keyword">end</span></pre></code></p>
<p>The <span class="caps">HTML</span> generation returns <span class="caps">ERB</span>, and a hash of variables necessary for
resolving it. (In this case we could also have used string substitution, but
that&#8217;s not always the case&#8212;you might want to make use of variables that are
only available at generation time.) Note that it also makes use of some of the
convenient helper functions (like <code>link_to</code> and <code>h</code>), which I&#8217;ve helpfully
defined for you in html.rb.</p>
<p>So that&#8217;s how to modify ditz&#8217;s models, views and controllers in one easy go.
You can add fields and helper methods to model objects (including the
configuration object), you can add commands to the controller, and you can add
view elements to the screen and <span class="caps">HTML</span> output.</p>
<p>For reference, the complete source code to the git plugin is
<a href="http://gitorious.org/projects/ditz/repos/mainline/blobs/master/lib%2Fplugins%2Fgit.rb%22">here</a>.</p>
  <div class="comment-link">
    
    <a  href="/old26#comments">No comments</a>.
  </div>

  <h2><a  href="/old34">ditz git integration plugin, in git</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="20 months ago">June 26, 2008  6:00pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/ditz/">ditz</a></span> <span class='label'><a  href="/label/git/">git</a></span> </div>
  
  <p class='first'>I&#8217;ve fleshed out <a href="http://ditz.rubyforge.org/&#39;s">ditz</a> plugin architecture and just added a plugin that ties it more closely to git. With this plugin enabled, you can tie issues to feature branches and automatically get a list of commits on that branch (until they&#8217;re merged into master, at which point that becomes impossible, thanks to the magic of git).</p>
<p>Here&#8217;s an example: Sup&#8217;s <a href="http://sup.rubyforge.org/ditz/issue-bdd4415a9d4c8fd3602500111bf9268aa7c7c6a4.html">configurable colors</a> issue.</p>
<p>With these changes, Ditz is now firmly in the <span class="caps">MVC</span> camp. The models are created from yaml objects on disk; the views are an <span class="caps">HTML</span> renderer (using <span class="caps">ERB</span>) and a screen renderer (using puts technology), and the controller is the previously-mentioned <a href="http://gitorious.org/projects/ditz/repos/mainline/blobs/master/lib/operator.rb">operator.rb</a>.</p>
<p>If you look at the <a href="http://gitorious.org/projects/ditz/repos/mainline/blobs/master/lib/plugins/git-features.rb">plugin code</a> you see that it need to modify all three of these components. It adds fields to the Issue and Config objects, it adds output to the <span class="caps">HTML</span> and screen views, and it adds commands to the controller. The fact that it can do this in a few lines of code is pretty sweet.</p>
  <div class="comment-link">
    
    <a  href="/old34#comments">Two comments by <b>William</b> and <b>Jing Xue</b></a>.
  </div>




  </div>

  <div id="footer" style="margin: 0px;">
    Served up by <a href="http://masanjin.net/whisper/">Whisper</a>. Yes!
  </div>
</div>
</body>
</html>
