hp12c
2015-02-20T15:34:20+09:00
http://melborne.github.io
kyoendo
[email protected]
Rubyによる暗黙のFizzBuzzの世界
2015-02-19T00:00:00+09:00
http://melborne.github.io/2015/02/19/implicit-fizzbuzz-in-ruby
<p><a href="http://qiita.com/supermomonga/items/b8faf7441ada9c310282" title="Rubyによる不適切なFizzBuzzの世界 - Qiita">Rubyによる不適切なFizzBuzzの世界 - Qiita</a>が、FizzBuzzerを刺激するから…。</p>
<h2 id="fizzbuzz-with-toproc">1. FizzBuzz with to_proc</h2>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">FizzBuzz</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">to_proc</span>
<span class="o">-></span><span class="n">n</span><span class="p">{</span>
<span class="k">case</span> <span class="mi">0</span>
<span class="k">when</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">15</span> <span class="k">then</span> <span class="ss">:FizzBuzz</span>
<span class="k">when</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">3</span> <span class="k">then</span> <span class="ss">:Fizz</span>
<span class="k">when</span> <span class="n">n</span> <span class="o">%</span> <span class="mi">5</span> <span class="k">then</span> <span class="ss">:Buzz</span>
<span class="k">else</span> <span class="n">n</span>
<span class="k">end</span>
<span class="p">}</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="nb">puts</span> <span class="p">(</span><span class="mi">1</span><span class="p">.</span><span class="nf">.</span><span class="mi">100</span><span class="p">).</span><span class="nf">map</span><span class="p">(</span><span class="o">&</span><span class="no">FizzBuzz</span><span class="p">)</span> <span class="c1"># => [1, 2, :Fizz, 4, :Buzz, :Fizz, 7, 8, :Fizz, :Buzz, 11, :Fizz, 13, 14, :FizzBuzz, 16, 17, :Fizz, 19, :Buzz, :Fizz, 22, 23, :Fizz, :Buzz, 26, :Fizz, 28, 29, :FizzBuzz, 31, 32, :Fizz, 34, :Buzz, :Fizz, 37, 38, :Fizz, :Buzz, 41, :Fizz, 43, 44, :FizzBuzz, 46, 47, :Fizz, 49, :Buzz, :Fizz, 52, 53, :Fizz, :Buzz, 56, :Fizz, 58, 59, :FizzBuzz, 61, 62, :Fizz, 64, :Buzz, :Fizz, 67, 68, :Fizz, :Buzz, 71, :Fizz, 73, 74, :FizzBuzz, 76, 77, :Fizz, 79, :Buzz, :Fizz, 82, 83, :Fizz, :Buzz, 86, :Fizz, 88, 89, :FizzBuzz, 91, 92, :Fizz, 94, :Buzz, :Fizz, 97, 98, :Fizz, :Buzz]</span></code></pre></div>
<h2 id="fizzbuzz-with-coerce">2. FizzBuzz with coerce</h2>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">module</span> <span class="nn">Base</span>
<span class="k">def</span> <span class="nf">div_by</span><span class="p">(</span><span class="n">base</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="o">!</span><span class="n">n</span><span class="p">.</span><span class="nf">is_a?</span><span class="p">(</span><span class="no">Fixnum</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">n</span> <span class="o">%</span> <span class="n">base</span><span class="p">).</span><span class="nf">zero?</span> <span class="p">?</span> <span class="nb">self</span> <span class="p">:</span> <span class="n">n</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">coerce</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="p">[</span><span class="nb">self</span><span class="p">,</span> <span class="n">n</span><span class="p">]</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">FizzBuzz</span>
<span class="kp">extend</span> <span class="no">Base</span>
<span class="k">class</span> <span class="o"><<</span> <span class="nb">self</span>
<span class="k">def</span> <span class="nf">|</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="n">div_by</span><span class="p">(</span><span class="mi">15</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Fizz</span>
<span class="kp">extend</span> <span class="no">Base</span>
<span class="k">class</span> <span class="o"><<</span> <span class="nb">self</span>
<span class="k">def</span> <span class="nf">|</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="n">div_by</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">class</span> <span class="nc">Buzz</span>
<span class="kp">extend</span> <span class="no">Base</span>
<span class="k">class</span> <span class="o"><<</span> <span class="nb">self</span>
<span class="k">def</span> <span class="nf">|</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="n">div_by</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="nb">puts</span> <span class="p">(</span><span class="mi">1</span><span class="p">.</span><span class="nf">.</span><span class="mi">100</span><span class="p">).</span><span class="nf">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">n</span><span class="o">|</span> <span class="n">n</span> <span class="o">|</span> <span class="no">FizzBuzz</span> <span class="o">|</span> <span class="no">Fizz</span> <span class="o">|</span> <span class="no">Buzz</span> <span class="p">}</span> <span class="c1"># => [1, 2, Fizz, 4, Buzz, Fizz, 7, 8, Fizz, Buzz, 11, Fizz, 13, 14, FizzBuzz, 16, 17, Fizz, 19, Buzz, Fizz, 22, 23, Fizz, Buzz, 26, Fizz, 28, 29, FizzBuzz, 31, 32, Fizz, 34, Buzz, Fizz, 37, 38, Fizz, Buzz, 41, Fizz, 43, 44, FizzBuzz, 46, 47, Fizz, 49, Buzz, Fizz, 52, 53, Fizz, Buzz, 56, Fizz, 58, 59, FizzBuzz, 61, 62, Fizz, 64, Buzz, Fizz, 67, 68, Fizz, Buzz, 71, Fizz, 73, 74, FizzBuzz, 76, 77, Fizz, 79, Buzz, Fizz, 82, 83, Fizz, Buzz, 86, Fizz, 88, 89, FizzBuzz, 91, 92, Fizz, 94, Buzz, Fizz, 97, 98, Fizz, Buzz]</span></code></pre></div>
<p>ちょっと挙動がユニークだけど…</p>
<p>変態度が足りませんでしたm(__)m</p>
<p>(追記:2015-02-20) 親切な解説を追加しました。</p>
<h2 id="fizzbuzz-with-toproc-1">FizzBuzz with to_procの親切な解説</h2>
<p>Rubyではメソッドに引数を渡すとき、<code>&</code>を前置するとそれをProcオブジェクトと理解しメソッドの実体に渡します。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">do_proc</span><span class="p">(</span><span class="o">&</span><span class="nb">proc</span><span class="p">)</span>
<span class="nb">proc</span><span class="p">.</span><span class="nf">call</span>
<span class="k">end</span>
<span class="c1"># または、</span>
<span class="k">def</span> <span class="nf">do_proc</span>
<span class="k">yield</span>
<span class="k">end</span>
<span class="nb">proc</span> <span class="o">=</span> <span class="o">-></span><span class="p">{</span> <span class="s1">'hey!'</span> <span class="p">}</span>
<span class="n">do_proc</span><span class="p">(</span><span class="o">&</span><span class="nb">proc</span><span class="p">)</span> <span class="c1"># => "hey!"</span></code></pre></div>
<p><code>&</code>を前置してProcオブジェクト以外のものを渡してみます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">def</span> <span class="nf">do_proc</span><span class="p">(</span><span class="o">&</span><span class="nb">proc</span><span class="p">)</span>
<span class="nb">proc</span><span class="p">.</span><span class="nf">call</span>
<span class="k">end</span>
<span class="nb">proc</span> <span class="o">=</span> <span class="s1">'hey!'</span>
<span class="n">do_proc</span><span class="p">(</span><span class="o">&</span><span class="nb">proc</span><span class="p">)</span> <span class="c1"># => </span>
<span class="c1"># ~> -:12:in `<main>': wrong argument type String (expected Proc) (TypeError)</span></code></pre></div>
<p>Procが期待されているとのエラーが吐かれました。</p>
<p>しかしRubyではそれを単に拒絶するのではなく、まずは渡されたオブジェクトがProcオブジェクトになり得るかを試す、つまりそのオブジェクトの<code>to_proc</code>メソッドを暗黙的にコールするのです。</p>
<p>‘hey!’オブジェクトにto_procを定義して再度試してみます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">proc</span> <span class="o">=</span> <span class="s1">'hey!'</span>
<span class="k">def</span> <span class="nc">proc</span><span class="o">.</span><span class="nf">to_proc</span>
<span class="o">-></span><span class="p">{</span> <span class="nb">self</span> <span class="p">}</span>
<span class="k">end</span>
<span class="n">do_proc</span><span class="p">(</span><span class="o">&</span><span class="nb">proc</span><span class="p">)</span> <span class="c1"># => "hey!"</span></code></pre></div>
<p>うまくいきました。</p>
<p>FizzBuzz with to_procではRubyのこの仕組みを利用しています。</p>
<p><code>FizzBuzz.to_proc</code>の中身は、@supermomongaさんによる<code>case 0</code>を使わせてもらいました。エレガントです。解説は次の記事を参照して下さい。</p>
<p><a href="http://qiita.com/supermomonga/items/b8faf7441ada9c310282" title="Rubyによる不適切なFizzBuzzの世界 - Qiita">Rubyによる不適切なFizzBuzzの世界 - Qiita</a></p>
<h2 id="fizzbuzz-with-coerce-1">FizzBuzz with coerceの親切な解説</h2>
<p>Rubyにおいて演算子の多くはメソッド呼び出しです。</p>
<p>つまりこれらは、</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="mi">1</span> <span class="o">+</span> <span class="mi">2</span> <span class="c1"># => 3</span>
<span class="mi">3</span> <span class="o">-</span> <span class="mi">4</span> <span class="c1"># => -1</span>
<span class="mi">5</span> <span class="o">*</span> <span class="mi">6</span> <span class="c1"># => 30</span>
<span class="mi">7</span> <span class="o">/</span> <span class="mi">8</span> <span class="c1"># => 0</span></code></pre></div>
<p>以下のシンタックスシュガーです。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="mi">1</span><span class="p">.</span><span class="nf">+</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span> <span class="c1"># => 3</span>
<span class="mi">3</span><span class="p">.</span><span class="nf">-</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span> <span class="c1"># => -1</span>
<span class="mi">5</span><span class="p">.</span><span class="nf">*</span><span class="p">(</span><span class="mi">6</span><span class="p">)</span> <span class="c1"># => 30</span>
<span class="mi">7</span><span class="p">.</span><span class="nf">/</span><span class="p">(</span><span class="mi">8</span><span class="p">)</span> <span class="c1"># => 0</span></code></pre></div>
<p>次のコードは、Rubyにおけるビット二項演算で論理和を求めるものですが、</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="mi">1</span> <span class="o">|</span> <span class="mi">0</span> <span class="c1"># => 1</span>
<span class="mi">0</span> <span class="o">|</span> <span class="mi">1</span> <span class="c1"># => 1</span>
<span class="mi">1</span> <span class="o">|</span> <span class="mi">1</span> <span class="c1"># => 1</span>
<span class="mi">0</span> <span class="o">|</span> <span class="mi">0</span> <span class="c1"># => 0</span></code></pre></div>
<p>これは<code>Fixnum#|</code>として実装されています。</p>
<p>FizzBuzz with coerceではこの<code>Fixnum#|</code>を呼んでいます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">puts</span> <span class="p">(</span><span class="mi">1</span><span class="p">.</span><span class="nf">.</span><span class="mi">100</span><span class="p">).</span><span class="nf">map</span> <span class="p">{</span> <span class="o">|</span><span class="n">n</span><span class="o">|</span> <span class="n">n</span> <span class="o">|</span> <span class="no">FizzBuzz</span> <span class="o">|</span> <span class="no">Fizz</span> <span class="o">|</span> <span class="no">Buzz</span> <span class="p">}</span></code></pre></div>
<p>mapのブロックの中で、最初にnとFizzBuzzクラスオブジェクトの論理和を求めています。</p>
<p>通常、<code>Fixnum#|</code>はその引数としてFixnumを期待しますが、それ以外のオブジェクトを渡すとどうなるかやってみます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">FizzBuzz</span>
<span class="k">end</span>
<span class="mi">3</span> <span class="o">|</span> <span class="no">FizzBuzz</span> <span class="c1"># => </span>
<span class="c1"># ~> -:22:in `|': Class can't be coerced into Fixnum (TypeError)</span>
<span class="c1"># ~> from -:22:in `<main>'</span></code></pre></div>
<p>クラスはFixnumにcoerce(強制型変換)できないとのエラーが吐かれました。</p>
<p>これでRubyがFizzBuzzクラスオブジェクトをFixnumに型変換、つまり<code>FizzBuzz.coerce</code>を暗黙的にコールしていることが分かりました。</p>
<p>これを実装してみます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">FizzBuzz</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">coerce</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">return</span> <span class="n">n</span><span class="p">,</span> <span class="mi">4</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="mi">3</span> <span class="o">|</span> <span class="no">FizzBuzz</span> <span class="c1"># => 7</span></code></pre></div>
<p>coerceでは、呼び出し元のオブジェクトを引数に取って、演算子の2つのオペランドが返るようにします。これにより<code>Fixnum#|</code>はこれらの値で実行されることになります。</p>
<p>ここでcoerceの最初の返り値に別のオブジェクトを渡すと、<code>Fixnum#|</code>の代わりにそのオブジェクトの<code>|</code>メソッドが呼ばれる、つまり<code>a_object#|</code>が実行されるようになります。</p>
<p><code>FizzBuzz.|</code>を定義して、やってみます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">FizzBuzz</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">|</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="s2">"</span><span class="si">#{</span><span class="n">n</span><span class="si">}</span><span class="s2"> received!"</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">coerce</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">self</span><span class="p">,</span> <span class="n">n</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="mi">3</span> <span class="o">|</span> <span class="no">FizzBuzz</span> <span class="c1"># => "3 received!"</span></code></pre></div>
<p>FizzBuzz with coerceではこのテクニックを使って、<code>Fixnum#|</code>の代わりに<code>FizzBuzz.|</code>が呼ばれるようにしています。</p>
<p>さて、次にFizzBuzz with coerceにおける<code>FizzBuzz.|</code>の実装を見てみます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">FizzBuzz</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">|</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="o">!</span><span class="n">n</span><span class="p">.</span><span class="nf">is_a?</span><span class="p">(</span><span class="no">Fixnum</span><span class="p">)</span> <span class="o">||</span> <span class="p">(</span><span class="n">n</span><span class="o">%</span><span class="mi">15</span><span class="p">).</span><span class="nf">zero?</span> <span class="p">?</span> <span class="nb">self</span> <span class="p">:</span> <span class="n">n</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">coerce</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">self</span><span class="p">,</span> <span class="n">n</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="mi">3</span> <span class="o">|</span> <span class="no">FizzBuzz</span> <span class="c1"># => 3</span>
<span class="mi">5</span> <span class="o">|</span> <span class="no">FizzBuzz</span> <span class="c1"># => 5</span>
<span class="mi">15</span> <span class="o">|</span> <span class="no">FizzBuzz</span> <span class="c1"># => FizzBuzz</span></code></pre></div>
<p>nが15で割り切れる場合はFizzBuzzクラスが、それ以外の場合はnが返ります。そしてFizzBuzz with coerceではこの値は次の段、つまりFizzとの演算に渡されます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="mi">3</span> <span class="o">|</span> <span class="no">Fizz</span> <span class="c1"># => Fizz</span>
<span class="mi">5</span> <span class="o">|</span> <span class="no">Fizz</span> <span class="c1"># => 5</span>
<span class="no">FizzBuzz</span> <span class="o">|</span> <span class="no">Fizz</span> <span class="c1"># => FizzBuzz</span></code></pre></div>
<p>Fizzクラスの実装は除算の基数が3である以外はFizzBuzzと同じです。よって、上の2つの場合は、FizzBuzzクラスと同様に動作し、nが3で割り切れる場合はFizzクラスが、それ以外の場合はnが返ることになります。</p>
<p>一方、FizzBuzzとFizzの演算では、FizzBuzzクラスの<code>|</code>メソッドが再度呼ばれることになります(ここがユニークなところです)。そしてその結果としてFizzBuzzクラスが返り、次の段に渡されることになります。</p>
<p>Buzzクラスでもこれと同様のことが起こり、一旦途中でFizzBuzz系クラスに変換されると、それがフォールスルーして最後まで維持されることになります。</p>
Ruby de Streem
2014-12-15T00:00:00+09:00
http://melborne.github.io/2014/12/15/ruby-de-streem
<blockquote>
<p>のっぴきならない事情で暫くここを離れてたけど</p>
<p>戻ってきたらMatzが新言語を作ってた</p>
<p>僕がいないうちにRubyは捨てられてしまったの?</p>
<p>僕が暫く目を離しているうちに世の中もMatzも変わってしまって</p>
<p>もうだれもRubyを愛さなくなってしまったの?</p>
</blockquote>
<hr />
<p><a href="https://github.com/matz/streem" title="matz/streem">matz/streem</a></p>
<h1 id="streem---stream-based-concurrent-scripting-language">Streem - stream based concurrent scripting language</h1>
<p>Streem is a concurrent scripting language based on a programming model
similar to shell, with influences from Ruby, Erlang and other
functional programming languages.</p>
<p>In Streem, a simple <code>cat</code> program looks like this:</p>
<div class="highlight"><pre><code class="language-bash" data-lang="bash">STDIN | STDOUT</code></pre></div>
<p>And a simple FizzBuzz will look like this:</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">seq</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span> <span class="o">|</span> <span class="p">{</span><span class="o">|</span><span class="n">x</span><span class="o">|</span>
<span class="k">if</span> <span class="n">x</span> <span class="o">%</span> <span class="mi">15</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span>
<span class="s2">"FizzBuzz"</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="n">x</span> <span class="o">%</span> <span class="mi">3</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span>
<span class="s2">"Fizz"</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span> <span class="n">x</span> <span class="o">%</span> <span class="mi">5</span> <span class="o">==</span> <span class="mi">0</span> <span class="p">{</span>
<span class="s2">"Buzz"</span>
<span class="p">}</span>
<span class="k">else</span> <span class="p">{</span>
<span class="n">x</span>
<span class="p">}</span>
<span class="p">}</span> <span class="o">|</span> <span class="no">STDOUT</span></code></pre></div>
<hr />
<h2 id="ruby-de-streem">Ruby de Streem</h2>
<blockquote>
<p>でも</p>
<p>心配いらないよ、Ruby</p>
<p>もう僕が戻ってきたんだから</p>
<p>僕はここにいるよ</p>
</blockquote>
<div><script src="https://gist.github.com/4516e808dd4784981aef.js?file=streem.rb"></script>
<noscript><pre><code></code></pre></noscript></div>
<div><script src="https://gist.github.com/4516e808dd4784981aef.js?file=example.rb"></script>
<noscript><pre><code></code></pre></noscript></div>
<p>ごめんなさいごめんなさい。</p>
<hr />
<p>関連記事:</p>
<blockquote>
<p><a href="http://melborne.github.io/2014/03/05/filter-in-ruby/" title="Rubyでパイプライン?">Rubyでパイプライン?</a></p>
</blockquote>
Ruby的FizzBuzz
2014-08-10T00:00:00+09:00
http://melborne.github.io/2014/08/10/fizzbuzzruby
<p><a href="http://qiita.com/tadsan/items/51d39ec7b49a8e8ee7fd" title="最終鬼畜FizzBuzz大全 - Qiita">最終鬼畜FizzBuzz大全 - Qiita</a>に刺激を受けて、<a href="http://qiita.com/merborne/items/15b4bbdb2bf46d7ad0c0" title="Ruby的FizzBuzz - Qiita">Qiita</a>のほうにポストしてみたんだけど、こちらは解説付きで。</p>
<h2 id="rubyfizzbuzz---">Ruby的FizzBuzz - その1</h2>
<p><br /></p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">FB</span>
<span class="k">def</span> <span class="nf">FizzBuzz</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="p">(</span><span class="n">n</span><span class="o">%</span><span class="mi">15</span><span class="p">)</span><span class="o">==</span><span class="mi">0</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">Fizz</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="p">(</span><span class="n">n</span><span class="o">%</span><span class="mi">3</span><span class="p">)</span><span class="o">==</span><span class="mi">0</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">Buzz</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="p">(</span><span class="n">n</span><span class="o">%</span><span class="mi">5</span><span class="p">)</span><span class="o">==</span><span class="mi">0</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">call</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="nb">instance_methods</span><span class="p">(</span><span class="kp">false</span><span class="p">).</span><span class="nf">detect</span> <span class="p">{</span> <span class="o">|</span><span class="n">m</span><span class="o">|</span> <span class="kp">new</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="p">}</span> <span class="o">||</span> <span class="n">n</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="p">(</span><span class="mi">1</span><span class="p">.</span><span class="nf">.</span><span class="mi">100</span><span class="p">).</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span> <span class="nb">printf</span> <span class="s2">"%s "</span><span class="p">,</span> <span class="no">FB</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="p">}</span>
<span class="c1"># >> 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz</span></code></pre></div>
<h3 id="section">解説</h3>
<ol>
<li><code>FB.call</code>の<code>instance_methods(false)</code>は、FBクラスに定義されたインスタンスメソッド名つまり<code>:FizzBuzz</code>, <code>:Fizz</code>, <code>:Buzz</code>の配列をそれらが定義された並びで返します。</li>
<li><code>detect</code>のブロックでは各メソッドが、callに渡された引数nを引数に呼び出されます。</li>
<li>各メソッドでは引数がそれぞれの基数で割り切れるかが判定されますが、<code>detect</code>では最初にtrueを返したメソッド名が返ることになります。例えばnが15のときは何れのメソッドの返り値もtrueになりますが、最初に評価される<code>:FizzBuzz</code>が返ります。</li>
<li>全メソッドの評価がfalseのときはdetectの返り値はnilになるので、<code>||</code>の右辺が実行され、結果引数nがそのまま返されることになります。</li>
</ol>
<h3 id="section-1">アピールポイント</h3>
<ol>
<li>文字列ではなくメソッド名に基いて出力の文字列を構成した点。</li>
<li>分岐的制御構造を使っていない点。</li>
</ol>
<h2 id="rubyfizzbuzz----1">Ruby的FizzBuzz - その2</h2>
<p><br /></p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="k">class</span> <span class="nc">FB</span>
<span class="k">def</span> <span class="nf">Fizz</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="p">(</span><span class="n">n</span><span class="o">%</span><span class="mi">3</span><span class="p">)</span><span class="o">==</span><span class="mi">0</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">Buzz</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="p">(</span><span class="n">n</span><span class="o">%</span><span class="mi">5</span><span class="p">)</span><span class="o">==</span><span class="mi">0</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">call</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="nb">instance_methods</span><span class="p">(</span><span class="kp">false</span><span class="p">).</span><span class="nf">select</span> <span class="p">{</span> <span class="o">|</span><span class="n">m</span><span class="o">|</span> <span class="kp">new</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span> <span class="p">}</span>
<span class="p">.</span><span class="nf">map</span><span class="p">(</span><span class="o">&</span><span class="ss">:to_s</span><span class="p">).</span><span class="nf">inject</span><span class="p">(:</span><span class="o">+</span><span class="p">)</span> <span class="o">||</span> <span class="n">n</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="p">(</span><span class="mi">1</span><span class="p">.</span><span class="nf">.</span><span class="mi">100</span><span class="p">).</span><span class="nf">each</span> <span class="p">{</span> <span class="o">|</span><span class="n">i</span><span class="o">|</span> <span class="nb">printf</span> <span class="s2">"%s "</span><span class="p">,</span> <span class="no">FB</span><span class="p">.</span><span class="nf">call</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="p">}</span>
<span class="c1"># >> 1 2 Fizz 4 Buzz Fizz 7 8 Fizz Buzz 11 Fizz 13 14 FizzBuzz 16 17 Fizz 19 Buzz Fizz 22 23 Fizz Buzz 26 Fizz 28 29 FizzBuzz 31 32 Fizz 34 Buzz Fizz 37 38 Fizz Buzz 41 Fizz 43 44 FizzBuzz 46 47 Fizz 49 Buzz Fizz 52 53 Fizz Buzz 56 Fizz 58 59 FizzBuzz 61 62 Fizz 64 Buzz Fizz 67 68 Fizz Buzz 71 Fizz 73 74 FizzBuzz 76 77 Fizz 79 Buzz Fizz 82 83 Fizz Buzz 86 Fizz 88 89 FizzBuzz 91 92 Fizz 94 Buzz Fizz 97 98 Fizz Buzz</span></code></pre></div>
<h3 id="section-2">解説</h3>
<ol>
<li>その1の発展型です。</li>
<li><code>FB.call</code>では、<code>detect</code>に代えて<code>select</code>を使い、trueを返すメソッドをすべて返すようにしています。例えば、nが15のときは<code>:Fizz</code>, <code>:Buzz</code>の両方が返ります。</li>
<li>配列内のシンボル値を<code>to_s</code>した後、<code>inject(:+)</code>でそれらを連結します。nが3のときは要素が<code>:Fizz</code>だけなので<code>Fizz</code>が返りますが、15のときは<code>:Fizz</code>, <code>:Buzz</code>が連結されて<code>FizzBuzz</code>が返ります。</li>
<li><code>Array#join</code>を使うという手もありましたが、空配列が<code>""</code>(空文字)になってしまうので、あとの処理が面倒なので避けました。</li>
</ol>
<h3 id="section-3">アピールポイント</h3>
<ol>
<li>selectを使い、Fizz, Buzzの2つのメソッドだけで3種類の出力をできるようにした点。</li>
</ol>
<p><br /></p>
<hr />
<p>御社採用、ご検討のほど、よろしくお願い申し上げますm(__)m</p>
Ruby製サードパーティライブラリgemのトレンドを知るには「BestGems.org」がベスト
2014-08-08T00:00:00+09:00
http://melborne.github.io/2014/08/08/bestgems-is-best-to-meet-new-gems
<h2 id="section">─質問1─</h2>
<blockquote>
<p>Ruby製サードパーティライブラリ、要は<code>gem</code>で、何が人気なのかってこと、手っ取り早く知りたいんですけど。</p>
</blockquote>
<h2 id="section-1">─回答1─</h2>
<blockquote>
<p><code>RubyGems.org</code>の<a href="https://rubygems.org/stats" title="stats">statsページ</a>を見てください。</p>
</blockquote>
<p><img src="/assets/images/2014/08/bestgems01.png" alt="bestgem noshadow" /></p>
<h2 id="section-2">─質問2─</h2>
<blockquote>
<p>えっ?これだけ?この辺は万年上位で固定でしょ。もうちょっと俺の知らないバラエティに富んだものに出会いたいんだけど。俺、Rails用ないし。</p>
</blockquote>
<h2 id="section-3">─回答2─</h2>
<blockquote>
<p>カテゴリー別なら<code>The Ruby Toolbox</code>があります。</p>
</blockquote>
<p><img src="/assets/images/2014/08/bestgems02.png" alt="bestgem noshadow" /></p>
<blockquote>
<p><a href="https://www.ruby-toolbox.com/categories/Terminal_Coloring" title="The Ruby Toolbox - Terminal Coloring">The Ruby Toolbox - Terminal Coloring</a></p>
</blockquote>
<h2 id="section-4">─質問3─</h2>
<blockquote>
<p>あんた、俺の質問ちゃんと聞いてるの?カテゴリー別なんて言ってないし。それに、ここのカテゴリーってなんか俺的に信用ないんだよね。取りこぼし多いっていうか..。俺のgem出てこないっていうか..。</p>
</blockquote>
<h2 id="section-5">─回答3─</h2>
<blockquote>
<p><code>GitHub</code>のTrendingでここ最近の人気リポジトリが分かります。</p>
</blockquote>
<p><img src="/assets/images/2014/08/bestgems03.png" alt="bestgem noshadow" /></p>
<blockquote>
<p><a href="https://github.com/trending?l=ruby&since=monthly" title="Trending Ruby repositories on GitHub this month">Trending Ruby repositories on GitHub this month</a></p>
</blockquote>
<p>これをメールで定期的にもらうこともできます。</p>
<blockquote>
<p><a href="https://github.com/explore/subscribe" title="Subscribe to GitHub's Explore Email">Subscribe to GitHub’s Explore Email</a></p>
</blockquote>
<p>ターミナルで見たいならgemがあります。</p>
<blockquote>
<p><a href="http://rochefort.hatenablog.com/entry/2014/06/09/070300" title="git-trend というrubygemsを作りました - rochefort's blog">git-trend というrubygemsを作りました - rochefort’s blog</a></p>
</blockquote>
<h2 id="section-6">─質問4─</h2>
<blockquote>
<p>まあ、これはこれでいいんだけどさ。でも俺、確か、<code>gem</code>って言ったよね、さっき?人気gemの再発見したいんだけど。</p>
</blockquote>
<h2 id="section-7">─回答4─</h2>
<p>@xmisaoさんが作った<code>BestGems.org</code>があります。約80,000個ある全gemの総合ダウンロードランキングが分かります。</p>
<p><img src="/assets/images/2014/08/bestgems04.png" alt="bestgem noshadow" /></p>
<blockquote>
<p><a href="http://bestgems.org/" title="BestGems -- Ruby Gems Download Ranking">BestGems – Ruby Gems Download Ranking</a></p>
</blockquote>
<p>BestGems.orgはオープンソースでもあります。</p>
<blockquote>
<p><a href="https://github.com/xmisao/bestgems.org" title="xmisao/bestgems.org">xmisao/bestgems.org</a></p>
</blockquote>
<h2 id="section-8">─質問5─</h2>
<p>ほぅ。じゃあ50番目に人気のあるgemが何かとかわかるの?</p>
<h2 id="section-9">─回答5─</h2>
<p><img src="/assets/images/2014/08/bestgems05.png" alt="bestgem noshadow" /></p>
<blockquote>
<p><a href="http://bestgems.org/total?page=3" title="Total">41-60 of all 79,598 gems</a></p>
</blockquote>
<p>前日のダウンロード数(日別)のランキングも分かります。</p>
<blockquote>
<p><a href="http://bestgems.org/daily" title="Daily Download Ranking -- Best Gems">Daily Download Ranking – Best Gems</a></p>
</blockquote>
<p>総合ランキングと日別ランキングの差から最近の人気度を図る<code>Featured</code>というものもあります。</p>
<p><img src="/assets/images/2014/08/bestgems06.png" alt="bestgem noshadow" /></p>
<blockquote>
<p><a href="http://bestgems.org/featured" title="Featured Gems Ranking -- Best Gems">Featured Gems Ranking – Best Gems</a></p>
</blockquote>
<h2 id="section-10">─質問6─</h2>
<p>おー、これいいね。なんか、面白いgem見つけられるかも。</p>
<p>あれ、そう言えば、日毎のダウンロード数って、<a href="http://guides.rubygems.org/rubygems-org-api/" title="RubyGems.org">RubyGems.orgのAPI</a>じゃ、取れなかったと思うんだけど。</p>
<h2 id="section-11">─回答6─</h2>
<p>BestGems.orgにおけるgemの個別ページでは、ダウンロード数やランキングの伸びをグラフで見ることができます。</p>
<p><img src="/assets/images/2014/08/bestgems07.png" alt="bestgem noshadow" /></p>
<blockquote>
<p><a href="http://bestgems.org/gems/power_assert" title="power_assert -- BestGems">power_assert – BestGems</a></p>
</blockquote>
<h2 id="section-12">─質問7─</h2>
<p>BestGems.orgは全gemについて日毎のダウンロード数、収集してるんだ。すごいな。そうすると、自分が作ったgemの成長過程をここで見ることもできる、ってわけだ。</p>
<p>いや、実は、自分の作ったgemのダウンロード数が気になっちゃって、ここのところ寝れなくってさ。勢いで、<code>mygegegems</code>ってgem作ったんだけど。あー、要はターミナルで自分のgemのダウンロード数見るやつ。</p>
<blockquote>
<p><a href="http://melborne.github.io/2014/07/14/count-your-gems-in-your-terminal/" title="自分が公開しているgemの日々のダウンロード数が気になって寝られません。どうしたらいいでしょうか(Yawhoo知恵袋)">自分が公開しているgemの日々のダウンロード数が気になって寝られません。どうしたらいいでしょうか(Yawhoo知恵袋)</a></p>
<p><a href="https://rubygems.org/gems/mygegegems" title="mygegegems">mygegegems</a></p>
</blockquote>
<p>これ、一応前日からのダウンロード数の伸びが分かるようになってるんだけど、こんな感じで。</p>
<p><img src="/assets/images/2014/08/bestgems08.png" alt="bestgem noshadow" /></p>
<p>で、これ、アクセスした日だけダウンロード数をYAMLファイルに記録するんだけど、アクセスしない日もあるしね..。YAMLにどこまでデータ溜めるんだって話もあるし。</p>
<p>BestGems.orgの収集したデータにアクセスするAPIでもあったら、捗るんだけどな…。</p>
<h2 id="section-13">─回答7─</h2>
<p><code>BestGems API</code>が公開されています。各gemについて、「総ダウンロード数」、「日別ダウンロード数」、「総合ランキング」および「日別ランキング」の各トレンド、つまりBestGems.org開設からの日毎のデータがJSONで取れます。</p>
<blockquote>
<p><a href="https://github.com/xmisao/bestgems.org/wiki/BestGems-API-v1-Specification" title="BestGems API v1 Specification · xmisao/bestgems.org Wiki">BestGems API v1 Specification · xmisao/bestgems.org Wiki</a></p>
</blockquote>
<h2 id="section-14">─質問8─</h2>
<p>えっ?API、あるの<sup id="fnref:1"><a href="#fn:1" rel="footnote">1</a></sup>?</p>
<pre><code>% curl http://bestgems.org/api/v1/gems/mygegegems/total_downloads.json
[{"date":"2014-08-07","total_downloads":583},{"date":"2014-08-06","total_downloads":569},{"date":"2014-08-05","total_downloads":569},{"date":"2014-08-04","total_downloads":563},{"date":"2014-08-03","total_downloads":557},{"date":"2014-08-02","total_downloads":550},{"date":"2014-08-01","total_downloads":544},{"date":"2014-07-31","total_downloads":542},{"date":"2014-07-30","total_downloads":534},{"date":"2014-07-29","total_downloads":489},{"date":"2014-07-28","total_downloads":466},{"date":"2014-07-27","total_downloads":444},{"date":"2014-07-26","total_downloads":441},{"date":"2014-07-25","total_downloads":441},{"date":"2014-07-24","total_downloads":428},{"date":"2014-07-23","total_downloads":359},{"date":"2014-07-22","total_downloads":326},{"date":"2014-07-21","total_downloads":326},{"date":"2014-07-20","total_downloads":312},{"date":"2014-07-19","total_downloads":303},{"date":"2014-07-18","total_downloads":303},{"date":"2014-07-17","total_downloads":303},{"date":"2014-07-16","total_downloads":301},{"date":"2014-07-15","total_downloads":255},{"date":"2014-07-14","total_downloads":202},{"date":"2014-07-13","total_downloads":141},{"date":"2014-07-12","total_downloads":6}]
</code></pre>
<p>おー、これはうれしい。</p>
<p>するってーと、だ。俺としてはこのデータを、Rubyのオブジェクトとして取り込めればいいんだな。まずは、ラッパークライアント書くか。</p>
<h2 id="section-15">─回答8─</h2>
<p>BestGems.org APIのRubyラッパーライブラリ<code>bestgems</code>があります。</p>
<blockquote>
<p><a href="https://rubygems.org/gems/bestgems" title="bestgems">bestgems</a></p>
<p><a href="https://github.com/melborne/bestgems" title="melborne/bestgems">melborne/bestgems</a></p>
</blockquote>
<p>こう使います。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s1">'bestgems'</span>
<span class="n">client</span> <span class="o">=</span> <span class="no">Bestgems</span><span class="p">.</span><span class="nf">client</span>
<span class="n">client</span><span class="p">.</span><span class="nf">total_downloads</span><span class="p">(</span><span class="ss">:rack</span><span class="p">)</span> <span class="c1"># => {"2014-08-08"=>48484297, "2014-08-07"=>48426620, "2014-08-06"=>48365953, "2014-08-05"=>48305390, "2014-08-04"=>48246069, "2014-08-03"=>48203248, ... }</span>
<span class="n">client</span><span class="p">.</span><span class="nf">daily_downloads</span><span class="p">(</span><span class="ss">:rack</span><span class="p">)</span> <span class="c1"># => {"2014-08-08"=>57677, "2014-08-07"=>60667, "2014-08-06"=>60563, "2014-08-05"=>59321, "2014-08-04"=>42821, "2014-08-03"=>30640, ... }</span>
<span class="n">client</span><span class="p">.</span><span class="nf">total_ranking</span><span class="p">(</span><span class="ss">:rack</span><span class="p">)</span> <span class="c1"># => {"2014-08-08"=>2, "2014-08-07"=>2, "2014-08-06"=>2, "2014-08-05"=>2, "2014-08-04"=>2, "2014-08-03"=>2, "2014-08-02"=>2, "2014-08-01"=>2, "2014-07-31"=>2, ... }</span>
<span class="n">client</span><span class="p">.</span><span class="nf">daily_ranking</span><span class="p">(</span><span class="ss">:rack</span><span class="p">)</span> <span class="c1"># => {"2014-08-08"=>6, "2014-08-07"=>6, "2014-08-06"=>6, "2014-08-05"=>7, "2014-08-04"=>4, "2014-08-03"=>3, "2014-08-02"=>3, "2014-08-01"=>6, "2014-07-31"=>6, ... }</span></code></pre></div>
<h2 id="section-16">─質問9─</h2>
<p>おー、こりゃ助かる。これ、誰が作ったの?</p>
<h2 id="section-17">─回答9─</h2>
<p>あなた様です<sup id="fnref:2"><a href="#fn:2" rel="footnote">2</a></sup>。</p>
<h2 id="section-18">─質問10─</h2>
<p>そうか、じゃあちょっと信用ならなぃ..。えっ?俺?…そうか、昨日書いたのか…。記憶力落ちたな。あー<a href="https://github.com/octokit/octokit.rb" title="octokit/octokit.rb">octokit.rb</a>のコード<del>パクリ</del>ちらちら見ながら、書いてたわ..。</p>
<p>まあ、それはいいとして、BesGems.orgの話に戻るんだけど、全gemのランキングが分かるっていったよね?そうすると、不人気の、つまり「ぺけ」のほうのgemも分かるってことだよね?「不人気gemベスト50」とか、ちょっと興味あるな…。それ、見せてみてよ..。</p>
<h2 id="section-19">─回答10─</h2>
<p>こちらになります。</p>
<p><img src="/assets/images/2014/08/bestgems09.png" alt="bestgem noshadow" /></p>
<p>下から5番目…orz</p>
<hr />
<p>(追記:2014-8-9) bestgems gemの仕様変更に伴い記述(コード)を変更しました。</p>
<div class="footnotes">
<ol>
<li id="fn:1">実のところBestGems.orgのAPIはtwitter上での@xmisaoさんと僕とのやりとりで生まれたのでした。https://twitter.com/merborne/status/488681089586585600 <a href="#fnref:1" rev="footnote">↩</a></li><li id="fn:2">今日はこれが言いたかった <a href="#fnref:2" rev="footnote">↩</a></li>
</ol>
</div>
ターミナルにデジタル式デカ文字を出力する「digi_moji」の紹介
2014-08-04T00:00:00+09:00
http://melborne.github.io/2014/08/04/show-big-words-on-your-terminal-with-digimoji
<p>個人的にはターミナル文字の色付けツールである拙作「<a href="https://rubygems.org/gems/colcolor" title="colcolor">colcolor</a>」を気に入ってまして。</p>
<blockquote>
<p><a href="/2014/07/14/yet-another-terminal-color-for-ruby/" title="Yet Another Terminal Color for Ruby: Colcolorの紹介">Yet Another Terminal Color for Ruby: Colcolorの紹介</a></p>
<p><a href="https://rubygems.org/gems/colcolor" title="colcolor">colcolor</a></p>
</blockquote>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"colcolor"</span>
<span class="n">str</span> <span class="o">=</span> <span class="s2">"Languages: Python Lisp Ruby Perl Haskell Erlang"</span>
<span class="nb">puts</span> <span class="n">str</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:yellow</span><span class="p">,</span> <span class="ss">:blue</span><span class="p">,</span> <span class="ss">:magenta</span><span class="p">,</span> <span class="ss">:red</span><span class="p">,</span> <span class="ss">:yellow</span><span class="p">,</span> <span class="ss">:blue</span><span class="p">,</span> <span class="ss">:red</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">str</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:green</span><span class="p">,</span> <span class="ss">:blue</span><span class="p">,</span> <span class="n">cyclic</span><span class="ss">:true</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">str</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:red_bold</span><span class="p">,</span> <span class="n">regexp</span><span class="ss">:/</span><span class="n">ruby</span><span class="o">/</span><span class="n">i</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">str</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:black_magenta</span><span class="p">,</span> <span class="n">cyclic</span><span class="ss">:true</span><span class="p">,</span> <span class="n">regexp</span><span class="ss">:/</span><span class="o">^</span><span class="p">\</span><span class="n">w</span><span class="o">+|</span><span class="p">[</span><span class="no">A</span><span class="o">-</span><span class="no">Z</span><span class="p">]</span><span class="o">/</span><span class="p">)</span></code></pre></div>
<p><img src="/assets/images/2014/08/digi_moji1.png" alt="digi_moji noshadow" /></p>
<p>このデモ的なものを作って宣伝できないかと考えたわけです。</p>
<p>それで「<a href="https://rubygems.org/gems/digi_moji" title="digi_moji">digi_moji</a>」なるツールが生まれました。</p>
<p>で、ステマをしたのですが…</p>
<blockquote>
<p><a href="http://melborne.github.io/2014/08/04/can-you-see-words-on-your-terminal/" target="_blank">わかりやすいREADME.mdの書き方がわかりません。どうしたらいいでしょうか(Yawhoo知恵袋) - digi_mojiのステマ </a><a href="http://b.hatena.ne.jp/entry/http://melborne.github.io/2014/08/04/can-you-see-words-on-your-terminal/" class="http-bookmark" target="_blank"><img src="http://b.hatena.ne.jp/entry/image/http://melborne.github.io/2014/08/04/can-you-see-words-on-your-terminal/" alt="error" class="http-bookmark" /></a></p>
</blockquote>
<p>見事にコケましたorz</p>
<hr />
<p>そんなわけで…。</p>
<p>ここでちゃんと<code>digi_moji</code>の紹介記事を書いておくことにします。</p>
<h2 id="digimoji">DigiMojiとは</h2>
<p>5x7で構成されたデジタル文字をターミナルに表示するためのツールです。裏で先の<code>colcolor</code>を使っているので文字にANSIカラーによる色付けができます。</p>
<blockquote>
<p><a href="https://rubygems.org/gems/digi_moji" title="digi_moji">digi_moji</a></p>
<p><a href="https://github.com/melborne/digi_moji" title="melborne/digi_moji">melborne/digi_moji</a></p>
</blockquote>
<p><code>gem install digi_moji</code>すると、<code>digi_moji</code>というターミナルコマンドが一緒にインストールされて使えるようになります。</p>
<pre><code>% digi_moji help
Commands:
digi_moji help [COMMAND] # Describe available commands or one specific command
digi_moji new WORD # Print a digital word
digi_moji time # Print current time
digi_moji timer SEC # Print count down timer
Options:
-f, [--fg=FG] # Foreground color
# Default: bg_white
-b, [--bg=BG] # Background color
-c, [--cell=CELL] # Cell character
-w, [--width=N] # Character width
# Default: 2
</code></pre>
<h2 id="digimoji-new">digi_moji newコマンド</h2>
<p>ターミナル上に単純に文字を出力するには<code>digi_moji new</code>コマンドを使います。引数として出力したい文字を渡します。</p>
<pre><code>% digi_moji new BIGGER
</code></pre>
<p><img src="/assets/images/2014/08/digi_moji2.png" alt="digi_moji noshadow" /></p>
<p>スペースを含むときは文字列をクオートしてください。</p>
<p><code>new</code>コマンドにはいくつかのオプションがあります。</p>
<pre><code>% digi_moji help new
Usage:
digi_moji new WORD
Options:
-f, [--fg=FG] # Foreground color
# Default: bg_white
-b, [--bg=BG] # Background color
-c, [--cell=CELL] # Cell character
-w, [--width=N] # Character width
# Default: 2
Print a digital word
</code></pre>
<p>色を付けてみます。</p>
<pre><code>% digi_moji new BIGGER --fg=bg_red --bg=bg_blue
</code></pre>
<p><img src="/assets/images/2014/08/digi_moji3.png" alt="digi_moji noshadow" /></p>
<p>色指定の際の注意点は、<code>--fg</code>、<code>--bg</code>ともに、<code>bg_<color></code>のように背景色指定を渡すことです。これは文字を構成する各セルがスペース(空文字)で表現されているので、前景色を指定しても色が出ないためです。</p>
<p>各セルの文字を空文字以外にセットすると前景色が効くようになります。</p>
<pre><code>% digi_moji new BIGGER --fg=green --cell=B
</code></pre>
<p><img src="/assets/images/2014/08/digi_moji4.png" alt="digi_moji noshadow" /></p>
<p>前景色が効くようになると、<code>blink</code>や<code>underscore</code>などのテキスト属性が使えるようになります。</p>
<pre><code>% digi_moji new BIGGER --fg=green_bold --cell=B --bg=green_blink
</code></pre>
<p><img src="/assets/images/2014/08/digi_moji5.gif" alt="digi_moji noshadow" /></p>
<p><code>--fg</code>、<code>--bg</code>に渡す引数のフォーマットは<code>colcolor</code>のそれに倣っていますので、先に示したcolcolorの記事を参考にしてください。</p>
<p>文字の大きさを調整したい場合は、<code>--width</code>オプションを使います。デフォルトは<code>2</code>です。</p>
<p><img src="/assets/images/2014/08/digi_moji6.png" alt="digi_moji noshadow" /></p>
<p>英大文字、英小文字、キーボード上に表記された記号には概ね対応しています。</p>
<p><img src="/assets/images/2014/08/digi_moji7.png" alt="digi_moji noshadow" /></p>
<h2 id="digimoji-time">digi_moji timeコマンド</h2>
<p>デジタル文字の代表と言えば、それは「デジタル時計」です。<code>time</code>コマンドはまさにそのためのコマンドです。</p>
<pre><code>% digi_moji time -f=bg_cyan
</code></pre>
<p><img src="/assets/images/2014/08/digi_moji8.gif" alt="digi_moji noshadow" /></p>
<p>ターミナル上に好きな色のデジタル時計を表示できます。<code>Ctrl+c</code>で終了します。</p>
<p>色を工夫すれば、オリジナリティ溢れた時計が作れます。</p>
<pre><code>% digi_moji time -f=cyan -b=yellow_blink -c=T
</code></pre>
<p><img src="/assets/images/2014/08/digi_moji9.gif" alt="digi_moji noshadow" /></p>
<p>いや、ちょっと見づらいですか。</p>
<h2 id="digimoji-timer">digi_moji timerコマンド</h2>
<p>「デジタル時計」があるなら「タイマー」もほしいと思うのが人情です。<code>timer</code>コマンドは引数で渡した時間(デフォルトで秒)を計測するカウントダウンタイマーを出力します。</p>
<pre><code> % digi_moji timer 5 -f=bg_magenta
</code></pre>
<p><img src="/assets/images/2014/08/digi_moji10.gif" alt="digi_moji noshadow" /></p>
<p><code>timer</code>コマンドには追加のオプションとして、<code>--unit</code>、<code>--message</code>、<code>--message-color</code>があります。</p>
<pre><code>% digi_moji help timer
Usage:
digi_moji timer SEC
Options:
-m, [--message=MESSAGE] # Message on time's up
# Default: TIME'S UP!
-k, [--message-color=MESSAGE_COLOR] # Message color
# Default: bg_red
-u, [--unit=UNIT] # Argument unit
# Default: sec
-f, [--fg=FG] # Foreground color
# Default: bg_white
-b, [--bg=BG] # Background color
-c, [--cell=CELL] # Cell character
-w, [--width=N] # Character width
# Default: 2
</code></pre>
<p><code>--unit</code>は引数の単位を変えるもので、’min’, ‘hour’が渡せます。<code>--message</code>は終了メッセージとして”TIME’S UP!”以外を表示できるようにします。<code>--message-color</code>はそのメッセージの色を指定します。</p>
<pre><code>% digi_moji timer 3 -u=min -f=bg_green -m=EAT -k=bg_yellow
</code></pre>
<p><img src="/assets/images/2014/08/digi_moji11.gif" alt="digi_moji noshadow" /></p>
<h2 id="ruby">Rubyスクリプトからの使い方</h2>
<p>デジ文字は<code>DigiMoji::String.new</code>で生成します。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"digi_moji"</span>
<span class="n">str</span> <span class="o">=</span> <span class="no">DigiMoji</span><span class="o">::</span><span class="no">String</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"RUBY"</span><span class="p">,</span> <span class="n">fg</span><span class="ss">:'bg_red'</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">str</span></code></pre></div>
<p>出力です。</p>
<p><img src="/assets/images/2014/08/digi_moji12.png" alt="digi_moji noshadow" /></p>
<p><code>String#to_digimoji</code>を用意してあるので、このコードは次のように書くこともできます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"digi_moji"</span>
<span class="n">str</span> <span class="o">=</span> <span class="s2">"RUBY"</span><span class="p">.</span><span class="nf">to_digimoji</span><span class="p">(</span><span class="n">fg</span><span class="ss">:'bg_red'</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">str</span></code></pre></div>
<p>いまのところインスタンスメソッドは、<code>+</code>、<code>join</code>、<code><<</code>の結合系メソッドだけです。<code>join</code>はオプションを渡しやすくするための<code>+</code>のエイリアスです。<code><<</code>はデジ文字を破壊的に結合します。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">str</span> <span class="o">=</span> <span class="s2">"RUBY"</span><span class="p">.</span><span class="nf">to_digimoji</span><span class="p">(</span><span class="n">fg</span><span class="ss">:'bg_red'</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">str</span> <span class="o">+</span> <span class="s2">"IST"</span>
<span class="nb">puts</span>
<span class="nb">puts</span> <span class="n">str</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s2">"IST"</span><span class="p">,</span> <span class="n">fg</span><span class="ss">:'bg_green'</span><span class="p">)</span>
<span class="nb">puts</span>
<span class="nb">puts</span> <span class="n">str</span>
<span class="nb">puts</span>
<span class="n">str</span> <span class="o"><<</span> <span class="s2">"IST"</span>
<span class="nb">puts</span>
<span class="nb">puts</span> <span class="n">str</span></code></pre></div>
<p><img src="/assets/images/2014/08/digi_moji13.png" alt="digi_moji noshadow" /></p>
<p>各結合系メソッドには、<code>DigiMoji::String</code>オブジェクトを渡してもいいです。</p>
<h2 id="section">特殊文字</h2>
<p>いくつかの非ASCII文字に特殊文字が割り当てられています。</p>
<p><code>≤</code>文字にはARROW_LEFT、<code>≥</code>文字にはARROW_RIGHT、<code>¬</code>文字にはARROW_UP、<code>—</code>文字にはARROW_DOWNが割り当てられています。同様に、<code>÷</code>文字にはDIVIDE、<code>æ</code>文字にはBLOCKが割り当てられています。これらの文字は、<code>alt + <key></code>のコンビネーションでそれぞれ入力可能です(<code>alt + ,</code>、<code>alt + .</code>、<code>alt + L</code>、<code>alt + ;</code>、<code>alt + /</code>、<code>alt + '</code>)。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"digi_moji"</span>
<span class="n">chars</span> <span class="o">=</span> <span class="sx">%w(≤ ≥ ¬ — ÷ æ)</span>
<span class="n">colors</span><span class="o">=</span> <span class="sx">%w(red green yellow blue magenta cyan)</span><span class="p">.</span><span class="nf">to_enum</span>
<span class="n">chars</span><span class="p">.</span><span class="nf">map!</span> <span class="p">{</span> <span class="o">|</span><span class="n">char</span><span class="o">|</span> <span class="n">char</span><span class="p">.</span><span class="nf">to_digimoji</span><span class="p">(</span><span class="n">fg</span><span class="ss">:"bg_</span><span class="si">#{</span><span class="n">colors</span><span class="p">.</span><span class="nf">next</span><span class="si">}</span><span class="ss">"</span><span class="p">)</span> <span class="p">}</span>
<span class="nb">puts</span> <span class="n">chars</span><span class="p">.</span><span class="nf">inject</span> <span class="p">{</span> <span class="o">|</span><span class="n">m</span><span class="p">,</span> <span class="n">char</span><span class="o">|</span> <span class="n">m</span> <span class="o">+</span> <span class="n">char</span> <span class="p">}</span></code></pre></div>
<p><img src="/assets/images/2014/08/digi_moji14.png" alt="digi_moji noshadow" /></p>
<h2 id="section-1">デジ文字のユーザ定義</h2>
<p>使われていない非ASCII文字を使って、独自のデジ文字を登録することができます。<code>Ω</code>(alt + z)を登録してみます。</p>
<p>デジ文字の登録には、<code>DigiMoji::Char.register</code>を使います。第1引数に登録する文字、第2引数にデジ文字を構成するセルを配列で定義します。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"digi_moji"</span>
<span class="no">DigiMoji</span><span class="o">::</span><span class="no">Char</span><span class="p">.</span><span class="nf">register</span><span class="p">(</span><span class="s2">"Ω"</span><span class="p">,</span> <span class="sx">%w(f f f f f
f t t t f
t f f f t
t f f f t
t f f f t
f t f t f
t t f t t)</span><span class="p">)</span>
<span class="nb">puts</span> <span class="s2">"18.3Ω"</span><span class="p">.</span><span class="nf">to_digimoji</span><span class="p">(</span><span class="n">fg</span><span class="ss">:'bg_green'</span><span class="p">)</span></code></pre></div>
<p>コードにあるように、セルの定義は文字<code>t</code>と<code>f</code>の1次元配列で行います。<code>t</code>の箇所が文字の形を構成します。</p>
<p><img src="/assets/images/2014/08/digi_moji15.png" alt="digi_moji noshadow" /></p>
<p>以上で説明を終わります。まあ、どんな場面で使えるかわかりませんが、<code>digi_moji</code>をよろしくです!</p>
<blockquote>
<p><a href="https://rubygems.org/gems/digi_moji" title="digi_moji">digi_moji</a></p>
<p><a href="https://github.com/melborne/digi_moji" title="melborne/digi_moji">melborne/digi_moji</a></p>
</blockquote>
わかりやすいREADME.mdの書き方がわかりません。どうしたらいいでしょうか(Yawhoo知恵袋) - digi_mojiのステマ
2014-08-04T00:00:00+09:00
http://melborne.github.io/2014/08/04/can-you-see-words-on-your-terminal
<h2 id="section">質問</h2>
<p>【ID非公開さん】</p>
<blockquote>
<p>GitHubで自作ツールを公開して世界中の人に使ってもらいたいと考えています。でも自分は英語が苦手です。どうしたらいいでしょうか。</p>
</blockquote>
<h2 id="section-1">ベストアンサーに選ばれた回答</h2>
<p>【SOTAさん】</p>
<p>この記事を読んでください。</p>
<blockquote>
<p><a href="http://deeeet.com/writing/2014/07/31/readme/" title="わかりやすいREADME.mdを書く SOTA">わかりやすいREADME.mdを書く SOTA</a></p>
</blockquote>
<h2 id="section-2">ベストアンサー以外の回答</h2>
<p>【melborneさん】</p>
<p>ビジュアルに訴えるツールを作って、README.mdをそのスクショで埋めます。英文は最小限に留めましょう。作ったツールがビジュアルに訴えないもののときは、<a href="https://rubygems.org/gems/gviz" title="gviz">gviz</a>などのツールを使って説明をビジュアライズしてください。以下にサンプルを示します。</p>
<h2 id="readmemd">README.mdのサンプル</h2>
<p>以下は、チンピラgem作者の<code>melborne</code>さんの<code>digi_moji</code>というツールのREADME.mdです。英語がちょっと怪しいですが、スクショがあることでツールの目的が明確になっています。</p>
<blockquote>
<p><a href="https://rubygems.org/gems/digi_moji" title="digi_moji">digi_moji</a></p>
<p><a href="https://github.com/melborne/digi_moji" title="melborne/digi_moji">melborne/digi_moji</a></p>
</blockquote>
<hr />
<h1 id="digimoji">DigiMoji</h1>
<p><a href="https://travis-ci.org/melborne/digi_moji"><img src="https://travis-ci.org/melborne/digi_moji.svg" alt="Build Status" /></a></p>
<p>5x7 digital color words on your terminal.</p>
<h2 id="installation">Installation</h2>
<p>Add this line to your application’s Gemfile:</p>
<pre><code>gem 'digi_moji'
</code></pre>
<p>And then execute:</p>
<pre><code>$ bundle
</code></pre>
<p>Or install it yourself as:</p>
<pre><code>$ gem install digi_moji
</code></pre>
<h2 id="usage-in-your-terminal">Usage in your terminal</h2>
<h3 id="new-command">new command</h3>
<p>Try <code>digi_moji new</code> command with words:</p>
<pre><code>% digi_moji new RUBY
</code></pre>
<p><img src="https://github.com/melborne/digi_moji/raw/screenshot/sample1.png" alt="sample1" /></p>
<pre><code>% digi_moji new RUBY --fg=bg_red --bg=bg_yellow
</code></pre>
<p><img src="https://github.com/melborne/digi_moji/raw/screenshot/sample2.png" alt="sample2" /></p>
<pre><code>% digi_moji new RUBY --fg=red --bg=red_blink --cell='R'
</code></pre>
<p><img src="https://github.com/melborne/digi_moji/raw/screenshot/sample3.gif" alt="sample3" /></p>
<h3 id="time-command">time command</h3>
<p><code>digi_moji time</code> outputs current time:</p>
<p><img src="https://github.com/melborne/digi_moji/raw/screenshot/sample4.gif" alt="sample4" /></p>
<h3 id="timer-command">timer command</h3>
<p><code>digi_moji timer</code> outputs count down timer:</p>
<p><img src="https://github.com/melborne/digi_moji/raw/screenshot/sample5.gif" alt="sample5" /></p>
<p><code>digi_moji help</code> for more info.</p>
<h2 id="usage-as-ruby-script">Usage as ruby script</h2>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s1">'digi_moji'</span>
<span class="n">str</span> <span class="o">=</span> <span class="no">DigiMoji</span><span class="o">::</span><span class="no">String</span><span class="p">.</span><span class="nf">new</span><span class="p">(</span><span class="s2">"HE"</span><span class="p">,</span> <span class="n">fg</span><span class="ss">:'bg_green'</span><span class="p">,</span> <span class="n">bg</span><span class="ss">:'bg_yellow'</span><span class="p">)</span>
<span class="nb">puts</span> <span class="n">str</span>
<span class="nb">puts</span>
<span class="nb">puts</span> <span class="n">str</span> <span class="o">+</span> <span class="s2">"LLO!"</span>
<span class="nb">puts</span>
<span class="nb">puts</span> <span class="n">str</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s2">"LP!"</span><span class="p">,</span> <span class="n">fg</span><span class="ss">:'bg_red'</span><span class="p">)</span></code></pre></div>
<p>Output:</p>
<p><img src="https://github.com/melborne/digi_moji/raw/screenshot/sample6.png" alt="sample6" /></p>
<h2 id="contributing">Contributing</h2>
<ol>
<li>Fork it ( https://github.com/[my-github-username]/digi_moji/fork )</li>
<li>Create your feature branch (<code>git checkout -b my-new-feature</code>)</li>
<li>Commit your changes (<code>git commit -am 'Add some feature'</code>)</li>
<li>Push to the branch (<code>git push origin my-new-feature</code>)</li>
<li>Create a new Pull Request</li>
</ol>
<hr />
<p><code>digi_moji</code>をよろしくね!</p>
カラム指向ターミナルカラーライブラリ「colcolor」にcyclicオプションを付けました!
2014-07-28T00:00:00+09:00
http://melborne.github.io/2014/07/28/examples-of-colcolor-cycle-option
<p>先日、カラム指向ターミナルカラーライブラリ「colcolor」というのを公開しまして。</p>
<blockquote>
<p><a href="/2014/07/14/yet-another-terminal-color-for-ruby/" title="Yet Another Terminal Color for Ruby: Colcolorの紹介">Yet Another Terminal Color for Ruby: Colcolorの紹介</a></p>
<p><a href="https://rubygems.org/gems/colcolor" title="colcolor">colcolor</a></p>
</blockquote>
<p>colcolorはStringクラスに<code>colco</code>というメソッドを挿します。colcoでは引数として複数の色名を受け取って単語区切りで文字を彩色します。こんな感じです。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"colcolor"</span>
<span class="no">DATA</span><span class="p">.</span><span class="nf">each_line</span><span class="p">.</span><span class="nf">with_index</span> <span class="k">do</span> <span class="o">|</span><span class="n">line</span><span class="p">,</span> <span class="n">i</span><span class="o">|</span>
<span class="nb">puts</span> <span class="n">line</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:green</span><span class="p">,</span> <span class="ss">:yellow</span><span class="p">,</span> <span class="ss">:blue</span><span class="p">,</span> <span class="ss">:blue</span><span class="p">)</span>
<span class="nb">puts</span> <span class="s2">"-"</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:red</span><span class="p">)</span> <span class="o">*</span> <span class="n">line</span><span class="p">.</span><span class="nf">size</span> <span class="k">if</span> <span class="n">i</span><span class="p">.</span><span class="nf">zero?</span>
<span class="k">end</span>
<span class="cp">__END__
lang year designer
Ruby 1993 Yukihiro Matsumoto
Lisp 1958 John McCarthy
C++ 1983 Bjarne Stroustrup</span></code></pre></div>
<p>ターミナル出力です。</p>
<p><img src="/assets/images/2014/07/colcolor_cycle1.png" alt="colcolor noshadow" /></p>
<h2 id="cyclic">cyclicオプション</h2>
<p>で、この度<code>cyclic</code>オプションをcolcoに渡せるようにしたので、紹介します。</p>
<p>colcolorでは渡した色数が単語数に対して不足するとき、残りの単語は色付けされないのですが、このcyclicオプションを<code>true</code>にセットすると、与えられた色を残りの単語に対しても繰り返し適用するようになります。こんな感じです。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"colcolor"</span>
<span class="n">text</span> <span class="o">=<<-</span><span class="no">EOS</span><span class="sh">
A dynamic, open source programming language
with a focus on simplicity and productivity.
It has an elegant syntax that is natural to
read and easy to write.
</span><span class="no">EOS</span>
<span class="nb">puts</span> <span class="n">text</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:red</span><span class="p">,</span> <span class="ss">:green</span><span class="p">,</span> <span class="ss">:blue</span><span class="p">,</span> <span class="ss">:yellow</span><span class="p">,</span> <span class="n">cyclic</span><span class="ss">:true</span><span class="p">)</span></code></pre></div>
<p>ターミナル出力です。</p>
<p><img src="/assets/images/2014/07/colcolor_cycle2.png" alt="colcolor noshadow" /></p>
<p>赤、緑、青、黄が単語に対して繰り返し適用されている様子がわかります。</p>
<p><code>regexp</code>オプションと組み合わせると、少し面白いこともできます。regexpに<code>/./</code>を渡して色区切りを文字ベースにしてみます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"colcolor"</span>
<span class="n">text</span> <span class="o">=<<-</span><span class="no">EOS</span><span class="sh">
A dynamic, open source programming language
with a focus on simplicity and productivity.
It has an elegant syntax that is natural to
read and easy to write.
</span><span class="no">EOS</span>
<span class="nb">puts</span> <span class="n">text</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:red</span><span class="p">,</span> <span class="ss">:green</span><span class="p">,</span> <span class="ss">:blue</span><span class="p">,</span> <span class="ss">:yellow</span><span class="p">,</span> <span class="n">cyclic</span><span class="ss">:true</span><span class="p">,</span> <span class="n">regexp</span><span class="ss">:/</span><span class="p">.</span><span class="nf">/</span><span class="p">)</span></code></pre></div>
<p>ターミナル出力です。</p>
<p><img src="/assets/images/2014/07/colcolor_cycle3.png" alt="colcolor noshadow" /></p>
<p>こんなこともできます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"colcolor"</span>
<span class="n">line</span> <span class="o">=</span> <span class="s2">" "</span> <span class="o">*</span> <span class="mi">50</span>
<span class="n">colors</span> <span class="o">=</span> <span class="sx">%i(bg_red bg_yellow)</span>
<span class="mi">10</span><span class="p">.</span><span class="nf">times</span> <span class="k">do</span>
<span class="nb">puts</span> <span class="n">line</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="o">*</span><span class="n">colors</span><span class="p">.</span><span class="nf">rotate!</span><span class="p">,</span> <span class="n">cyclic</span><span class="ss">:true</span><span class="p">,</span> <span class="n">regexp</span><span class="ss">:/</span><span class="p">.</span><span class="nf">.</span><span class="sr">/)
end</span></code></pre></div>
<p>ターミナル出力です。</p>
<p><img src="/assets/images/2014/07/colcolor_cycle4.png" alt="colcolor noshadow" /></p>
<p><code>colcolor</code>をどうぞよろしく!</p>
<blockquote>
<p><a href="/2014/07/14/yet-another-terminal-color-for-ruby/" title="Yet Another Terminal Color for Ruby: Colcolorの紹介">Yet Another Terminal Color for Ruby: Colcolorの紹介</a></p>
<p><a href="https://rubygems.org/gems/colcolor" title="colcolor">colcolor</a></p>
<p><a href="https://github.com/melborne/colcolor" title="melborne/colcolor">melborne/colcolor</a></p>
</blockquote>
<hr />
<p>(追記:2014-7-30) オプション名を”cycle”から”cyclic”に変更しました(version 0.0.5)。</p>
Yet Another Terminal Color for Ruby: Colcolorの紹介
2014-07-14T00:00:00+09:00
http://melborne.github.io/2014/07/14/yet-another-terminal-color-for-ruby
<p>巷にはターミナル文字のカラー化を楽にするライブラリが溢れています。僕も以前にその幾つかを紹介した記事を書きました。</p>
<blockquote>
<p><a href="/2010/11/07/Ruby-ANSI/" title="RubyでANSIカラーシーケンスを学ぼう!">RubyでANSIカラーシーケンスを学ぼう!</a></p>
</blockquote>
<p>にも拘わらずみんな、人の作ったライブラリが自分のテイストに合わないのか、自分用に、しかし他と似たようなものをまた作って、このリストを更に長くしていくという傾向があるようです。<a href="https://rubygems.org/search?utf8=%E2%9C%93&query=color" title="RubyGems.org">RubyGems.org</a>で<code>color</code>を検索してみてください。僕が言っていることが冗談ではないということが分かるでしょう。</p>
<p>これだけ大量のカラー化ライブラリがあるとどれを選ぶべきか皆目わからず、人気どころを2、3試してみてそれらが合わなかったら、他を探すより自分で作ったほうが早い、となるのも頷けます。</p>
<p>え〜、それで、ちょっと言いづらいのですが…。</p>
<p>ご多分に漏れず…。</p>
<p><br /></p>
<p>「Colcolor」というgemを作りましたよ!> まじか。</p>
<blockquote>
<p><a href="https://rubygems.org/gems/colcolor" title="colcolor">colcolor</a></p>
<p><a href="https://github.com/melborne/colcolor" title="melborne/colcolor">melborne/colcolor</a></p>
</blockquote>
<h2 id="colcolor">Colcolorの特徴</h2>
<p>殆どのカラーライブラリは、Stringにカラー用のメソッドを挿して、そのメソッドで文字列の前後にエスケープシーケンスを挿入します。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="s2">"Charlie"</span><span class="p">.</span><span class="nf">red</span> <span class="c1"># => "\e[31mChalie\e[0m"</span></code></pre></div>
<p><code>colcolor</code>もその点は他のライブラリと同じで、Stringに<code>colco</code>というインスタンスメソッドを追加します。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="s2">"Charlie"</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:red</span><span class="p">)</span> <span class="c1"># => "\e[31mChalie\e[0m"</span></code></pre></div>
<p><code>colcolor</code>が特徴的なのは、他のライブラリが行指向のものであるのに対して、列(カラム)指向である点です。つまり一行におけるホワイトスペースで区切られたカラムを認識し、それ毎に異なるカラーを適用できるのです。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="s2">"Charlie 21 programmer"</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:red</span><span class="p">,</span> <span class="ss">:yellow</span><span class="p">,</span> <span class="ss">:cyan</span><span class="p">)</span> <span class="c1"># => "\e[31mCharlie\e[0m \e[33m21\e[0m \e[36mprogrammer\e[0m"</span></code></pre></div>
<p>例えば、タブ区切りのリストにおいて、そのカラムごとに色を変えたい場合は、次のように簡単にできます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="nb">require</span> <span class="s2">"colcolor"</span>
<span class="n">list</span> <span class="o">=</span> <span class="o"><<-</span><span class="no">EOS</span><span class="sh">
Charlie</span><span class="se">\t</span><span class="sh">21</span><span class="se">\t</span><span class="sh">programmer
Bill</span><span class="se">\t</span><span class="sh">43</span><span class="se">\t</span><span class="sh">doctor
Liz</span><span class="se">\t</span><span class="sh">18</span><span class="se">\t</span><span class="sh">student
</span><span class="no">EOS</span>
<span class="n">list</span><span class="p">.</span><span class="nf">each_line</span> <span class="k">do</span> <span class="o">|</span><span class="n">line</span><span class="o">|</span>
<span class="nb">puts</span> <span class="n">line</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:green</span><span class="p">,</span> <span class="ss">:yellow</span><span class="p">,</span> <span class="ss">:blue</span><span class="p">)</span>
<span class="k">end</span></code></pre></div>
<p>出力です。</p>
<p><img src="/assets/images/2014/07/colco1.png" alt="Alt title noshadow" /></p>
<p>背景色を作りたいときは、<code>:bg_green</code>などとします。</p>
<h2 id="section">複数属性の適用</h2>
<p>一つのカラムに対して、前景色と背景色など複数の属性を適用したい場合は、アンダースコア(<code>_</code>)で属性をつなぎます。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">list</span><span class="p">.</span><span class="nf">each_line</span> <span class="k">do</span> <span class="o">|</span><span class="n">line</span><span class="o">|</span>
<span class="nb">puts</span> <span class="n">line</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:green</span><span class="p">,</span> <span class="ss">:red_yellow</span><span class="p">,</span> <span class="ss">:blue_underline</span><span class="p">)</span>
<span class="k">end</span></code></pre></div>
<p>最初の色が前景色、2つ目以降が背景色になります。出力です。</p>
<p><img src="/assets/images/2014/07/colco2.png" alt="Alt title noshadow" /></p>
<p>緑背景に赤文字を点滅させたいときは、<code>:red_green_blink</code>などとします。</p>
<h2 id="section-1">カスタムカラムパターン</h2>
<p>デフォルトではホワイトスペースをカラムの区切りと認識して各色を適用しますが、<code>regexp</code>オプションでこれをカスタマイズできます。</p>
<p>例えば、リストにスペースで区切られた名前と苗字が含まれていて、そこは連続した背景色にしたい場合、次のようにします。</p>
<div class="highlight"><pre><code class="language-ruby" data-lang="ruby"><span class="n">list</span> <span class="o">=</span> <span class="o"><<-</span><span class="no">EOS</span><span class="sh">
Charlie Brown</span><span class="se">\t</span><span class="sh">21</span><span class="se">\t</span><span class="sh">programmer
Bill Clinton</span><span class="se">\t</span><span class="sh">43</span><span class="se">\t</span><span class="sh">doctor
Liz Taylor</span><span class="se">\t</span><span class="sh">18</span><span class="se">\t</span><span class="sh">student
</span><span class="no">EOS</span>
<span class="c1"># 不適切な例:</span>
<span class="n">list</span><span class="p">.</span><span class="nf">each_line</span> <span class="k">do</span> <span class="o">|</span><span class="n">line</span><span class="o">|</span>
<span class="nb">puts</span> <span class="n">line</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:bg_green</span><span class="p">,</span> <span class="ss">:bg_green</span><span class="p">,</span> <span class="ss">:yellow</span><span class="p">,</span> <span class="ss">:blue_underline</span><span class="p">)</span>
<span class="k">end</span>
<span class="nb">puts</span>
<span class="c1"># regexpオプションを使った例:</span>
<span class="n">re</span> <span class="o">=</span> <span class="sr">/^.*?(?=\t)|\S+/</span> <span class="c1"># 最初のタブの前、または空白以外にマッチ</span>
<span class="n">list</span><span class="p">.</span><span class="nf">each_line</span> <span class="k">do</span> <span class="o">|</span><span class="n">line</span><span class="o">|</span>
<span class="nb">puts</span> <span class="n">line</span><span class="p">.</span><span class="nf">colco</span><span class="p">(</span><span class="ss">:bg_green</span><span class="p">,</span> <span class="ss">:yellow</span><span class="p">,</span> <span class="ss">:blue_underline</span><span class="p">,</span> <span class="n">regexp</span><span class="ss">:re</span><span class="p">)</span>
<span class="k">end</span></code></pre></div>
<p>出力です。</p>
<p><img src="/assets/images/2014/07/colco3.png" alt="Alt title noshadow" /></p>
<p>良かったら試してみてください。</p>
<p>以上、Yet Another Terminal Color for Rubyのお話でしたm(__)m</p>
<hr />
<blockquote>
<p><a href="https://rubygems.org/gems/colcolor" title="colcolor">colcolor</a></p>
<p><a href="https://github.com/melborne/colcolor" title="melborne/colcolor">melborne/colcolor</a></p>
</blockquote>
<hr />
<p>(追記:2014-7-28) </p>
<p><code>colcolor</code>にcycleオプションを付けました。</p>
<blockquote>
<p><a href="/2014/07/28/examples-of-colcolor-cycle-option/" title="カラム指向ターミナルカラーライブラリ「colcolor」にcycleオプションを付けました!">カラム指向ターミナルカラーライブラリ「colcolor」にcycleオプションを付けました!</a></p>
</blockquote>