<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>TIM Labs</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/" />
    <link rel="self" type="application/atom+xml" href="http://labs.timedia.co.jp/atom.xml" />
    <id>tag:labs.timedia.co.jp,2010-09-11://3</id>
    <updated>2012-05-15T10:12:20Z</updated>
    
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 5.02</generator>

<entry>
    <title>僕が一番 Vim のタブページをうまく使えるんだ(GNU screen 連携編)</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/05/vim-tabpages-and-gnu-screen.html" />
    <id>tag:labs.timedia.co.jp,2012://3.297</id>

    <published>2012-05-15T15:00:00Z</published>
    <updated>2012-05-15T10:12:20Z</updated>

    <summary>問題 僕が一番 Vim のタブページをうまく使えるんだ(カレントディレクトリ編) で述べたように、 Vimのタブページはとても便利ですが、 ちょっと工夫するだけでさらに便利になります。 ところで、一般に Vim を使うような方は黒い画面を眺...</summary>
    <author>
        <name>kana</name>
        
    </author>
    
    <category term="editorwar" label="editorwar" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="gnuscreen" label="gnuscreen" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="terminal" label="terminal" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="vim" label="vim" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<h3>問題</h3>

<p><a href="http://labs.timedia.co.jp/2012/05/vim-tabpagecd.html">僕が一番 Vim のタブページをうまく使えるんだ(カレントディレクトリ編)</a>
で述べたように、
<a href="http://vimdoc.sourceforge.net/htmldoc/tabpage.html">Vimのタブページ</a>はとても便利ですが、
ちょっと工夫するだけでさらに便利になります。</p>

<p>ところで、一般に Vim を使うような方は<a href="http://en.wikipedia.org/wiki/File:Xterm.png">黒い画面</a>を眺める機会が多いと思います。
また、端末をより便利に使うために <a href="http://www.gnu.org/software/screen/">GNU screen</a> 等の端末マルチプレクサーを使用している方も多くいるはずです。
すると、 Vim でソースコードを編集しつつ、時折端末に切り替えて作業する......ということが多発します。</p>

<p>この時、以下の点で不便に感じることがあります。</p>

<ul>
<li>端末をアクティブにすることが面倒(GUI 版の Vim を使用している場合)。</li>
<li>作業用のウィンドウに切り替えることが面倒(GNU screen 内で Vim を起動している場合)。</li>
<li>シェルで作業ができる状態になったとしても、 Vim で注目しているカレントディレクトリに移動する手間がかかって面倒。</li>
</ul>

<p>特に最後の点が大問題で、
せっかく<a href="http://labs.timedia.co.jp/2012/05/vim-tabpagecd.html">タブページ毎にカレントディレクトリを設定</a>できるようにして便利さを高めたのにもかかわらず、
端末を使おうとするとその便利さも片手落ちという状態です。</p>

<p>つまり、 <strong>作業用のシェルにフォーカスを移し、さらにシェルのカレントディレクトリを Vim で注目しているディレクトリに切り替える</strong> ことが簡単にできるようにしたいものです。
しかし、一体全体どうすればよいのでしょうか。</p>
]]>
        <![CDATA[<h3>解答</h3>

<p>問題は</p>

<ol>
<li>端末をアクティブにする(GUI 版限定)。</li>
<li>作業用のウィンドウに切り替える。</li>
<li>作業用シェルのカレントディレクトリを切り替える。</li>
</ol>

<p>の3ステップに分解できます。
一つづつ片づけていきましょう。</p>

<h4>端末をアクティブにする</h4>

<p>例えば Mac OS X であれば以下のコマンドで端末をアクティブにできます:</p>

<pre><code>open -a Terminal
</code></pre>

<p>他の OS の場合や Mac OS X でも標準以外の端末エミュレーターを使用している場合のコマンドは各自の宿題とします。</p>

<h4>作業用のウィンドウに切り替える</h4>

<p>これを実現するために、まずどのウィンドウが「作業用」なのか定義しておく必要があります。
ここでは作業用のウィンドウのタイトルが <code>another</code> だとしておきましょう。</p>

<p>幸い、 GNU screen は他のプロセスから既に起動しているセッションに対してコマンドを送ることができます。
ですので、以下のコマンドで <code>another</code> ウィンドウに切り替えることができます:</p>

<pre><code>screen -X eval 'select another'
</code></pre>

<p>(ウィンドウの切り替えだけなら <code>eval</code> を使う必要はありませんが、
最後の問題で <code>eval</code> を使うので、この段階で予め <code>eval</code> を使う形で書いています)</p>

<h4>作業用シェルのカレントディレクトリを切り替える</h4>

<p><code>stuff</code> を使うと GNU screen 内の現在のウィンドウへ任意の文字列を送ることができます。
つまり以下のコマンドを実行すれば適切な <code>cd</code> を GNU screen から作業用シェルで行わせることが可能です:</p>

<pre><code>screen -X eval 'stuff "cd somewhere\015"'
</code></pre>

<p>ここで <code>\015</code> は <code>&lt;C-m&gt;</code> ≒ <code>&lt;Return&gt;</code> (若者言葉で言うところの <code>&lt;Enter&gt;</code>) を意味します。</p>

<h4>上記の設定を統合して Vim から簡単に「切り替え」できるようにする</h4>

<p>各問題が一通り解決できたので、後はその結果をまとめるだけです。
まとめ始めると長くなるので、<a href="https://github.com/kana/config/blob/a97ca68fcdba1f053fb0cbe4e5dae3b0f47ce5d9/vim/personal/dot.vimrc">筆者の vimrc</a> から必要な部分だけを抜粋します:</p>

<pre><code>function! s:activate_terminal()
  if !has('gui_running')
    return
  endif

  if has('macunix')
    silent !open -a Terminal
  else
    " This platform is not supported.
  endif
endfunction

if !exists('s:GNU_SCREEN_AVAILABLE_P')
  if has('gui_running')
    let s:GNU_SCREEN_AVAILABLE_P = executable('screen')
  else
    let s:GNU_SCREEN_AVAILABLE_P = len($WINDOW) != 0
  endif
endif

function! s:SuspendWithAutomticCD()
  if s:GNU_SCREEN_AVAILABLE_P
    call s:activate_terminal()

    silent execute '!screen -X eval'
    \              '''select another'''
    \              '''stuff "cd \"'.getcwd().'\"\015"'''
    redraw!
    let s:GNU_SCREEN_AVAILABLE_P = (v:shell_error == 0)
  endif

  if !s:GNU_SCREEN_AVAILABLE_P
    suspend
  endif
endfunction

noremap &lt;C-z&gt;  &lt;Nop&gt;
noremap! &lt;C-z&gt;  &lt;Nop&gt;
nnoremap &lt;C-z&gt;  :&lt;C-u&gt;call &lt;SID&gt;SuspendWithAutomticCD()&lt;Return&gt;
</code></pre>

<p>ここでは:</p>

<ul>
<li>GUI 版の Vim を利用しているケースは Mac OS X のみサポートしています。</li>
<li>作業用シェルへの切り替えは <code>&lt;C-z&gt;</code> で行う形にしています。</li>
</ul>

<p>前者は単に筆者のメイン環境が Mac OS X であることで、
後者は過去に筆者が <code>:suspend</code> を多用していた頃の名残です。</p>

<p>これで <code>&lt;C-z&gt;</code> を押下するだけで</p>

<ol>
<li>自動的に端末がアクティブになり、</li>
<li>作業用のシェルにフォーカスが合い、</li>
<li>さらには作業用のシェルのカレントディレクトリが Vim で注目中のディレクトリに切り替わる</li>
</ol>

<p>ようになります。
やりましたね。</p>

<h3>補足</h3>

<ul>
<li>前提条件が色々とあるため、上記の設定を vimrc にコピーすれば万人の環境ですぐに使えるというものではありません。各自の環境に合わせて適宜変更してください。</li>
<li>上記の設定は GNU screen の利用を前提としたものですが、 tmux 等の他の端末マルチプレクサーでも同様の設定ができると思います。</li>
<li>先述の通り、いささか好みや利用環境に依存するところが大きいため、プラグインとして分離していません。誰か一般化してください。</li>
<li>「 Vim の中でシェルを動かせばいい」というのは邪教徒の妄言なのでここでは無視しています。</li>
<li>次回は Emacs 編です。</li>
</ul>
]]>
    </content>
</entry>

<entry>
    <title>僕が一番 Vim のタブページをうまく使えるんだ(カレントディレクトリ編)</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/05/vim-tabpagecd.html" />
    <id>tag:labs.timedia.co.jp,2012://3.294</id>

    <published>2012-04-30T15:00:00Z</published>
    <updated>2012-04-27T09:08:08Z</updated>

    <summary>問題 Vimのタブページ はとても便利です。 例えばウィンドウを分割して複数のファイルを並行してにらめっこしていたとしましょう。 その最中に誰かからの依頼等で全く関係のない作業をやることになったとします。 このとき、 新しいタブページを開い...</summary>
    <author>
        <name>kana</name>
        
    </author>
    
    <category term="editorwar" label="editorwar" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="vim" label="vim" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<h3>問題</h3>

<p><a href="http://vimdoc.sourceforge.net/htmldoc/tabpage.html">Vimのタブページ</a>
はとても便利です。
例えばウィンドウを分割して複数のファイルを並行してにらめっこしていたとしましょう。
その最中に誰かからの依頼等で全く関係のない作業をやることになったとします。
このとき、</p>

<ol>
<li>新しいタブページを開いて、</li>
<li>そこで作業を進めて、</li>
<li>作業が完了したらタブページを閉じて、</li>
<li>先程まで行っていたにらめっこ作業を再開する</li>
</ol>

<p>という形で中断された作業をスムーズに再開することができます。
やりましたね。</p>

<p>しかし、これだけではまだタブページを全力全開で活用しきっているとは言えないのではないでしょうか。</p>
]]>
        <![CDATA[<p>例えば以下のような状況を考えてみましょう:</p>

<ul>
<li>あなたはプロジェクトAとプロジェクトBの両方を開発しています。</li>
<li>AとBは相互に連携しています。</li>
<li>大抵はAまたはBのどちらかの配下のファイルだけを編集するだけで十分です。</li>
<li>時には双方の配下のファイルを並行して編集する必要があります。</li>
</ul>

<p>このような状況で効率良く開発する方法は色々あると思いますが、
その一つとして
「プロジェクト毎に専用のタブページを用意して作業する」
というものがあります。
この例で言えばA用のタブページとB用のタブページをそれぞれ用意して、
各プロジェクトのファイルは専用のタブページでのみ開くということです。
ひとつのタブページ内で双方のプロジェクトのファイルを開いているとどこにどのファイルが表示されているのか混乱しがちだからです。</p>

<p>ただこの方式にはひとつ問題があります。
例えばAは <code>~/project/a</code> に、Bは <code>~/project/b</code> にあるとしましょう。</p>

<ul>
<li>カレントディレクトリを <code>~/project/a</code> に切り替えておけばAのファイルを開いたり <code>:grep</code> するのが簡単になります。</li>
<li>しかしこの状態でB用のタブページを表示してBに関する作業をしようとすると、
カレントディレクトリが <code>~/project/b</code> ではないため、
Bのファイルを開いたり <code>:grep</code> するには適宜追加のパスを入力しなければならず、面倒です。</li>
</ul>

<p>理想としては <strong>タブページ毎にカレントディレクトリを設定</strong> できれば良いのですが、
あいにくそのような機能はVimには存在しません。
似たような機能としては <code>:lcd</code> があるのですが、
これはウィンドウ毎にカレントディレクトリを設定するコマンドなので、
これでは切り替える単位が細かすぎて不便です。
どうすればよいでしょうか。</p>

<h3>解答</h3>

<p><a href="https://github.com/kana/vim-tabpagecd">vim-tabpagecd</a> を使います。</p>

<p>このプラグインをインストールすると <code>:cd</code> がタブページ単位で機能するようになります。
何も設定する必要はありません。
やりましたね。</p>

<p>このプラグインは実質10行程度の簡単な作りになっていますので、
Vimプラグイン作成のとっかかりにもちょうど良いでしょう。</p>

<h3>予告</h3>

<p>次回は Emacs 編です。</p>
]]>
    </content>
</entry>

<entry>
    <title>Sphinxで打ち消し線を使う</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/04/sphinx.html" />
    <id>tag:labs.timedia.co.jp,2012://3.296</id>

    <published>2012-04-27T02:20:32Z</published>
    <updated>2012-04-27T02:49:32Z</updated>

    <summary>Sphinx のベースになっている reST フォーマットには打ち消し線用の書式がありません。ですが、お仕事で文書を書いていると「ある仕様がなくなったこと」を示したいことがあるため、稀に打ち消し線を使いたくなることがあります。周りの人に聞い...</summary>
    <author>
        <name>tk0miya</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[Sphinx のベースになっている reST フォーマットには打ち消し線用の書式がありません。<div>ですが、お仕事で文書を書いていると「ある仕様がなくなったこと」を示したいことがあるため、</div><div>稀に打ち消し線を使いたくなることがあります。</div><div><br /></div><div>周りの人に聞いてみたところ、テーマをいじる方法や</div><div>各 reST におまじないを書く方法などを教えてもらったのですが、</div><div>ふとした時に使いたくなっても忘れてしまいそうな印象を受けました。</div><div><br /></div><div>そこで打ち消し線を簡単に使えるよう、簡単な拡張を作ってみました。</div>]]>
        <![CDATA[Sphinx プロジェクトのディレクトリに以下の内容を sphinxcontrib_roles.py という名前で保存します。
<div><script src="https://gist.github.com/2495330.js?file=sphinxcontrib_roles.py"></script></div>

次に conf.py の末尾に以下の記述を追加します。
<div><script src="https://gist.github.com/2495330.js?file=conf.py"></script></div>

ここでは strike、red という二つのロールを定義しています。
CSS の定義でそれぞれ打ち消し線表示、赤い文字にする、という表示にしています。

あとは reST 本文の中でこれらのロールを指定するだけです。
たとえば :strike:`ここは打ち消し線表示` と書いて HTML ファイルを生成すると
以下のように出力されます。
<img alt="define_roles.png" src="http://labs.timedia.co.jp/define_roles.png" width="1042" height="295" class="mt-image-none" style="" />

HTML 以外のフォーマットでは効果がありませんが、
HTML 出力はよく使われると思うので程よくマークアップすると良いと思います。
ただ、見た目ばかりに気を取られると Sphinx(reST) のメリットが薄れていくのでご注意を。]]>
    </content>
</entry>

<entry>
    <title>Apache JMeter実行時ログの日時表記を人が見てわかる形式(yyyy/mm/dd形式)にする</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/04/jmeter-log-dateformat.html" />
    <id>tag:labs.timedia.co.jp,2012://3.291</id>

    <published>2012-04-13T15:00:00Z</published>
    <updated>2012-04-11T09:27:43Z</updated>

    <summary>みなさん、負荷テストはどうやっているでしょうか。私は無償で且つ機能のそれなりということで、Apache JMeterをよく利用します。さて、JMeterを利用し負荷をかける際に当然ログをとります。後で解析する必要があるからです。その際、画面...</summary>
    <author>
        <name>SHIMANE, Yoshikazu</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[みなさん、負荷テストはどうやっているでしょうか。<br />私は無償で且つ機能のそれなりということで、<a href="http://jmeter.apache.org/">Apache JMeter</a>をよく利用します。<br /><br />さて、JMeterを利用し負荷をかける際に当然ログをとります。後で解析する必要があるからです。<br />その際、画面上時間表記になっている個所でもなにもせずログ出力を行うとJavaの実装通り1970年1月1日0時0分0秒UTCからのミリsecの値で出力されます。<br />たとえば、「2012年4月5日11:09:37(ミリ秒は省略)」であれば「1333591776885」のようになります。<br /><br />これを人間が見てわかる形、たとえば上記の「2012年4月5日11:09:37」のような「yyyy/mm/dd hh:mm:ss」フォーマットにする場合どうすればよいでしょうか。<br /><br />方法は二つあります。<br />]]>
        <![CDATA[一つ目は、ログ出力時の日付フォーマットをyyyy/mm/dd形式とする方法、もう一つが出力されたシリアル値をExcelを使って変換する方法です。<br /><br />一つ目の前者の場合行うことは<br /><blockquote><a class="keyword" href="http://d.hatena.ne.jp/keyword/jmeter">jmeter</a>.save.saveservice.timestamp_format<br /></blockquote>プロパティを設定します。<br />プロパティの内容は<a href="http://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html">java.text.SimpleDateFormat</a>で指定するフォーマットと同一です。たとえば、「2012/04/01 12:10:10」のような出力フォーマットにしたい場合は、<br /><blockquote>yyyy/MM/dd hh:mm:ss<br /></blockquote>となります。<br />実際のプロパティの設定は通常のJavaプログラム起動でのプロパティ指定と同様で、上記の例であれば<br /><blockquote>-D<a class="keyword" href="http://d.hatena.ne.jp/keyword/jmeter">jmeter</a>.save.saveservice.timestamp_format="yyyy/MM/dd hh:mm:ss"<br /></blockquote>とつけてJMeterを起動させます。<br />このオプションはJMeterを起動するシェルスクリプト/バッチ内で付けてよいですし、Windowsであればバッチのショートカットに付けても大丈夫です。<br />自分は試していませんが、$JMETER_HOME/bin/ 配下のプロパティファイルに追記してもいけそうな気がします。<br /><br />なおこの方法の難点は、設定せずに実行してしまった場合はどうしようもないということです。設定せずに実行してしまった、でももう一度実行するのは環境を占有する関係上できない、そういう場合は次に方法がよいでしょう。<br /><br />ということで二つ目の方法ですが、そのままExcelで変換する方法です。<br />一つ目の方法でフォーマット指定しない場合はシリアル値が出力されると書きました。Javaのシリアル値は1970年1月1日 UTCを基準にミリ秒(ms)で表現されます。一方Excelの場合は1900年1月1日UTC基準となります。この差を埋めた上で日付表記に変換をかける必要があるわけです。<br /><br />じゃあどうすればよいかというと、<a href="http://railsearch.s28.xrea.com/time.htm">このあたり</a>を参考にするといいでしょう。<br />上記サイトだと若干おかしな部分があるので修正し、シリアル値の変換式を<br /><blockquote>=( A1/86400000)+25569+0.375<br /></blockquote>とします。元の「86400」の部分を「86400000」としました。これは元サイトだとmsではなくsecで扱っているため時間のずれが生じるためです。<br /><br />こうすることですでに実行済みのJMeterログを解析する際、時刻を人が見てわかりやすい形式にすることができます。<br />]]>
    </content>
</entry>

<entry>
    <title>アニメ化決定! すべての Vim プラグインマネージャーは道を譲れ!!!!!!</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/04/vim-flavor-a-tool-to-manage-your-favorite-vim-plugins.html" />
    <id>tag:labs.timedia.co.jp,2012://3.288</id>

    <published>2012-03-31T15:00:00Z</published>
    <updated>2012-03-27T11:25:18Z</updated>

    <summary>問題 一旦 Vim がメキメキと使えるようになるとプラグインもバリバリと導入したくなります。 最初は数個のプラグインを試しに使っているだけだったのが、 時を経るにつれて数多のプラグインを使うようになってくるものです。 こうなると問題になるの...</summary>
    <author>
        <name>kana</name>
        
    </author>
    
    <category term="editorwar" label="editorwar" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="vim" label="vim" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<h3>問題</h3>

<p>一旦
<a href="http://www.vim.org/">Vim</a>
がメキメキと使えるようになるとプラグインもバリバリと導入したくなります。
最初は数個のプラグインを試しに使っているだけだったのが、
<a href="https://github.com/kana/config/blob/9e48eb3e41885f46366193f38b25a9ed54c92725/vim/VimFlavor">時を経るにつれて数多のプラグインを使うようになってくる</a>ものです。</p>

<p>こうなると問題になるのはプラグインの管理です。
数が増えてくると新しいものをインストールするのもインストール済みのものを新しいバージョンに更新するのも億劫になります。</p>

<p>そこで必要になるのが Vim プラグインを管理するためのツールです。
この手のツールは2008年8月に公開された <a href="https://github.com/tpope/vim-pathogen">vim-pathogen</a> が最古だと思われますが、
とりわけ民衆に認知され始めたのは <a href="http://conferences.yapcasia.org/ya2009/talk/2254">YAPC::Asia 2009 で発表</a> された
<a href="https://github.com/c9s/Vimana">Vimana</a> からだと思います。</p>

<p>この手の <a href="https://gist.github.com/2214365">Vim プラグインマネージャーは既にいくつかの実装が存在する</a>ものの、いずれも欠点が存在します。</p>
]]>
        <![CDATA[<h3>考察</h3>

<p>全ての設定、特に使用する <strong>プラグインのバージョン</strong> もバージョン管理システムの配下に置かれるべきです。
既存の実装は全て使用するプラグインのバージョンを管理しません。
これは <strong>複数の異なる環境で同一の設定を使用することが不可能</strong> ということです
(唯一の例外は <a href="https://github.com/tpope/vim-pathogen">vim-pathogen</a> を
Git のサブモジュール等と併用することですが、
数多のプラグインをサブモジュール等で手動管理するのは骨が折れます)。</p>

<p>プラグインが依存するプラグインを自動でインストールできるよう、
プラグインの依存関係を適切に記述する標準的なフォーマットもあるべきです。
既存の実装のほぼ全てが依存関係の自動解決できません
(唯一の例外は
<a href="https://github.com/MarcWeber/vim-addon-manager">vim-addon-manager</a>
ですが、これはプラグインが要求するバージョンを記述できません。
例えば他のプラグインから利用されるあるプラグインで過去のバージョンとは非互換な変更があった場合、
利用側が新バージョンに対応したものになるまでは非互換なバージョンはインストールすべきではありませんが、
これを自動でインストールしてしまう可能性があります)。</p>

<p>あらゆるソフトウェアには十分かつ再現可能なテストが含まれているべきです。
しかし既存の実装の一部、例えば
<a href="https://github.com/gmarik/vundle">vundle</a>
のテストは繰り返し実行して動作の成否を確認するための手順が含まれていませんし、
<a href="https://github.com/Shougo/neobundle.vim">neobundle</a>
に至っては一切のテストが存在しません。
ぶっちゃけありえない。</p>

<p>ツールのインストール手順は短く、
容易に再現可能で、
既存の環境に与える影響は可能な限り少なくすべきです。
既存の実装のほとんどは手動で <code>~/.vim</code> 等のディレクトリの調整が必要です。
vimfiles へのパスはプラットフォームによって異なるので、
この手の作業を異なる環境で手動で行うのは骨が折れます。</p>

<p>最後に、この手のツールは他のものへ容易に移行できるよう、
ツール自身とツールにより作成されたファイルやディレクトリは簡単に抹消できるべきです。
既存の実装のうち、特に <a href="https://github.com/c9s/Vimana">Vimana</a> は
<code>~/.vim/colors</code> 等へプラグインを直接デプロイするうえに
<code>uninstall</code> コマンド等もないためとても困ります。</p>

<p>さてどうしましょう。上記の観点から既存の実装は全て使い物になりません。
今日から始まる新生活を安心して送るためには一体どうすればよいでしょうか。</p>

<h3>解答</h3>

<p><a href="https://github.com/kana/vim-flavor">vim-flavor</a> を使います。</p>

<h4>必須要件</h4>

<ul>
<li><a href="http://git-scm.com/">Git</a> 1.7.9 以降</li>
<li><a href="http://www.ruby-lang.org/">Ruby</a> 1.9.2 以降
<ul>
<li>Ruby のインストールには <a href="http://beginrescueend.com/">RVM</a> 等を使うことを推奨します。複数の環境で同一の状況を作り上げるのが簡単になるからです。</li>
</ul></li>
<li><a href="http://www.vim.org/">Vim</a> 7.3 以降</li>
</ul>

<h4>サポートしているプラットフォーム</h4>

<ul>
<li>大抵の Unix-like な環境。</li>
<li>Microsoft Windows は直接サポートはしていませんが、
Cygwin 等を併用して間接的に管理することは可能です。</li>
</ul>

<h4>インストール手順</h4>

<pre><code>gem install vim-flavor
</code></pre>

<h4>インストールできるプラグイン</h4>

<ul>
<li>Git リポジトリが存在するものに限ります。
特に <a href="http://www.vim.org/">www.vim.org</a> で公開されているものは
<a href="http://vim-scripts.org/">vim-scripts.org</a>によって
<a href="https://github.com/vim-scripts">Git リポジトリしてのミラー</a>が提供されており、
「Git しか使えない」ことは取り立てて問題にはなりません。</li>
<li>プラグインの Git リポジトリにはバージョン毎にタグが作成されていることが前提です。
例えば git tag 1.2.3 等としてタグが作成されており、
このタグを使えばバージョン 1.2.3 のファイル一式が取得できるということです。</li>
<li>まともなディレクトリ構造を作成しているものに限ります。
例えば太古に www.vim.org で公開されているプラグインの中には単に
foo.vim だけがアップロードされており、それが
plugin/foo.vim なのか
syntax/foo.vim なのかあるいはそれ以外の何かなのか機械的に判別できないものがあります。
こういう状態のものはインストールできないということです。
ただこういう状態のものは現代ではまず存在しませんし、
<a href="https://github.com/vim-scripts/a.vim">vim-scripts.org によるミラーは割と良い感じに調整を施してある</a>ため、
これが問題になることもまずありません。</li>
</ul>

<h4>vim-flavor を使い始める</h4>

<pre><code>cd $YOUR_REPOSITORY_FOR_DOTFILES

cat &gt;VimFlavor &lt;&lt;'END'
  # * git://github.com/kana/vim-textobj-indent.git を使うと宣言します。
  # * 引数が '$USER/$REPO' の形式なら
  #   git://github.com/$USER/$REPO.git からプラグインを取得します。
  # * kana/vim-textobj-indent は kana/vim-textobj-user に依存しています。
  #   このような依存関係は自動解決されて必要なものがインストールされます。
  #   (プラグインが自身の依存関係を VimFlavor ファイルで記述している場合)
  #   (FIXME: 依存関係の自動解決は現段階では未実装です。直に実装されます)
  flavor 'kana/vim-textobj-indent'

  # * git://github.com/vim-scripts/fakeclip.git を使うと宣言します。
  # * 引数が '$REPO' の形式なら
  #   git://github.com/vim-scripts/$REPO.git からプラグインを取得します。
  flavor 'fakeclip'

  # * git://github.com/kana/vim-altr.git を使うと宣言します。
  # * 引数が URI ならそこからプラグインを取得します。
  flavor 'git://github.com/kana/vim-altr.git'

  # * kana/vim-smartchr 0.1.0 以降を使うと宣言します。
  #   ただし 0.2.0 以降のバージョンは(非互換かもしれないので)使いません。
  flavor 'kana/vim-smartchr', '~&gt; 0.1.0'

  # * kana/vim-smartword 0.1 以降を使うと宣言します。
  #   ただし 1.0 以降のバージョンは(まず非互換なので)使いません。
  flavor 'kana/vim-smartword', '~&gt; 0.1'

  # * kana/vim-smarttill 0.1.0 以降を使うと宣言します。
  #   特に使用するバージョンの上限は決めません。
  #   非互換であったとしても可能な限り新しいバージョンを使います。
  flavor 'kana/vim-smarttill', '&gt;= 0.1.0'
END

# VimFlavor で宣言したプラグインを取得し、
# VimFlavor.lock (使用するバージョン等の情報のスナップショット) を作成し、
# ~/.vim 等へ宣言したプラグインと初期設定用のスクリプトをデプロイします。
vim-flavor install

# vimrc のできるだけ最初の行に以下のコマンドを追加してください:
#
#   runtime flavors/bootstrap.vim
vim vimrc

git add VimFlavor VimFlavor.lock vimrc
git commit -m 'Use vim-flavor to manage my favorite Vim plugins'
</code></pre>

<h4>使用するプラグインのバージョンを更新する</h4>

<pre><code>vim-flavor upgrade

git add VimFlavor.lock
git commit -m 'Upgrade my favorite Vim plugins'
</code></pre>

<h4>新しいプラグインをインストールする</h4>

<pre><code>cat &gt;&gt;VimFlavor &lt;&lt;'END'

  flavor 'kana/vim-operator-replace'

END

# 新たに使用すると宣言されたプラグインを取得し、
# VimFlavor.lock を適宜更新し、
# ~/.vim 等へ宣言したプラグインをデプロイします。
vim-flavor install

git add VimFlavor VimFlavor.lock
git commit -m 'Use kana/vim-operator-replace'
</code></pre>

<h4>使わなくなったプラグインを削除する</h4>

<pre><code># VimFlavor から使わなくなったプラグインの宣言を削除する。
sed -i~ -e '/vim-smartchr/d' VimFlavor

# VimFlavor.lock を適宜更新し、
# ~/.vim 等から使わなくなったプラグインを削除します。
vim-flavor install

git add VimFlavor VimFlavor.lock
git commit -m 'Farewell kana/vim-smartchr'
</code></pre>

<h4>標準でない場所へプラグインをインストールする</h4>

<pre><code>vim-flavor install --vimfiles-path=/cygdrive/c/Users/kana/vimfiles
</code></pre>

<h4>vim-flavor を使うのを止める</h4>

<pre><code>rm -r ~/.vim-flavor
rm -r ~/.vim/flavors  # もしくは ~/vimfiles/flavors 等。

cd $YOUR_REPOSITORY_FOR_DOTFILES
rm VimFlavor VimFlavor.lock
git commit -am 'Farewell to vim-flavor'
</code></pre>

<h3>補足</h3>

<ul>
<li>今日はエイプリルフールです。</li>
<li>vim-flavor 自体は Ruby の gem として書かれていますが、
<a href="http://twitter.com/kana1">作者</a>の Ruby 力は低いので
Ruby 的に不味いところがあれば<a href="https://github.com/kana/vim-flavor/issues">ご指摘</a>いただけると幸いです。</li>
</ul>

<!-- vim: set expandtab softtabstop=4 shiftwidth=4 filetype=markdown : -->
]]>
    </content>
</entry>

<entry>
    <title>僕が一番 Vim の正規表現をうまく使えるんだ(\zs \ze 編)</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/03/vim-regular-expression-zs-ze.html" />
    <id>tag:labs.timedia.co.jp,2012://3.285</id>

    <published>2012-03-15T15:00:00Z</published>
    <updated>2012-03-15T10:22:15Z</updated>

    <summary>問題 Vim の正規表現 はとても豊富で、 ベーシックなもの から アドバンスドなもの までかなりの道具が揃っています。 これを駆使すればありとあらゆる......は言い過ぎですが、 世の中のテキスト処理の九分九厘を快適に行うことができます...</summary>
    <author>
        <name>kana</name>
        
    </author>
    
    <category term="editorwar" label="editorwar" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="regularexpression" label="regularexpression" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="vim" label="vim" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<h3>問題</h3>

<p><a href="http://vimdoc.sourceforge.net/htmldoc/pattern.html#pattern-overview">Vim の正規表現</a>
はとても豊富で、
<a href="http://vimdoc.sourceforge.net/htmldoc/pattern.html#/star">ベーシックなもの</a>
から
<a href="http://vimdoc.sourceforge.net/htmldoc/pattern.html#cursor-position">アドバンスドなもの</a>
までかなりの道具が揃っています。
これを駆使すればありとあらゆる......は言い過ぎですが、
世の中のテキスト処理の九分九厘を快適に行うことができます。</p>

<p>ただ、あまりにも数が多いので、一体どこから覚えていけばいいのか困りますし、
<code>:help</code> に記載されているものの中には<a href="http://vimdoc.sourceforge.net/htmldoc/pattern.html#/%5C%25U">今後の人生で活用する機会があるかどうか分からないもの</a>もあります。
手っ取り早く正規表現力を高めて生産性を向上するには一先ずどれを覚えれば良いのでしょうか。</p>
]]>
        <![CDATA[<h3>解答</h3>

<p>まずは
<a href="http://vimdoc.sourceforge.net/htmldoc/pattern.html#/%5Czs"><code>\zs</code></a>
と
<a href="http://vimdoc.sourceforge.net/htmldoc/pattern.html#/%5Cze"><code>\ze</code></a>
を覚えましょう。
この2つは正規表現のマッチの開始位置/終了位置を指定することができます。
これだけでは何のことやらさっぱりですが、以下のように応用することができます:</p>

<h4>「foobar」の「foo」を指定</h4>

<p><code>foo\zebar</code> で表現できます(Perl 語で言うところの <code>foo(?=bar)</code>)。
<code>foo\(bar\)\@=</code> でも同じものは表現できますが、
<code>\ze</code> を使う方が遥かに読み書きし易いです。</p>

<h4>「foobar」の「bar」を指定</h4>

<p><code>foo\zsbar</code> で表現できます(Perl 語で言うところの <code>(?&lt;=foo)bar</code>)。
<code>\(foo\)\@&lt;=bar</code> でも同じものは表現できますが、
<code>\zs</code> を使う方が遥かに読み書きし易いです。</p>

<h4>マッチしたテキストの一部だけを置換</h4>

<p>例えば</p>

<pre><code>&lt;li&gt;&lt;span&gt;...&lt;/span&gt;&lt;a href="..."&gt;&lt;span class="..."&gt; Close&lt;/span&gt;
&lt;span class="..."&gt; Open&lt;/span&gt;&lt;span class="..."&gt; Details&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
</code></pre>

<p>のような、いかにも機械的に生成されたHTMLをそれなりの見た目になるよう整形するとしましょう。</p>

<p>まずは適宜改行する必要があるのですが、これは <code>:%s/&gt;\zs\ze&lt;/\r/g</code> でできます。</p>

<pre><code>&lt;li&gt;
&lt;span&gt;...&lt;/span&gt;
&lt;a href="..."&gt;
&lt;span class="..."&gt; Close&lt;/span&gt;
&lt;span class="..."&gt; Open&lt;/span&gt;
&lt;span class="..."&gt; Details&lt;/span&gt;
&lt;/a&gt;
&lt;/li&gt;
</code></pre>

<p>ベタにやるなら <code>:%s/&gt;&lt;/&gt;\r&lt;/g</code> でも同じことができますし、
前後のパターンが複雑な場合でも <code>:%s/\(&gt;\)\(&lt;\)/\1\r\2/g</code> のようにすれば対応できます。
しかし <code>\zs</code> と <code>\ze</code> を使う方が入力の手間が省けますし、
置換する文字列に本質的でないものを指定しなくて済むので、
こちらの方が良いです。</p>

<p>後は <code>gg=G</code> 等として綺麗にインデントしましょう:</p>

<pre><code>&lt;li&gt;
  &lt;span&gt;...&lt;/span&gt;
  &lt;a href="..."&gt;
    &lt;span class="..."&gt; Close&lt;/span&gt;
    &lt;span class="..."&gt; Open&lt;/span&gt;
    &lt;span class="..."&gt; Details&lt;/span&gt;
  &lt;/a&gt;
&lt;/li&gt;
</code></pre>

<h3>予告</h3>

<p>次回は Emacs 編です。</p>
]]>
    </content>
</entry>

<entry>
    <title>Windows XP SP3 + .Net Framework 4.0の組み合わせではSHA256が使えない</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/02/windows-xp-sp3-net-framework-40sha256.html" />
    <id>tag:labs.timedia.co.jp,2012://3.243</id>

    <published>2012-02-28T00:00:00Z</published>
    <updated>2012-02-27T01:41:13Z</updated>

    <summary>ほとんどタイトルで言い尽くしてしまった感がありますが、Windows XP SP3 + .Net Framework 4.0 の環境では標準ライブラリにあるSHA256ハッシュ関数を使うことができません。いや、その環境では動かないと言ったほ...</summary>
    <author>
        <name>SHIMANE, Yoshikazu</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[ほとんどタイトルで言い尽くしてしまった感がありますが、Windows XP SP3 + .Net Framework 4.0 の環境では<a href="http://msdn.microsoft.com/ja-jp/library/system.security.cryptography.sha256cryptoserviceprovider.aspx">標準ライブラリにあるSHA256ハッシュ関数</a>を使うことができません。いや、その環境では動かないと言ったほうがいいでしょう。<br /><br />上記リンク先のMSDNのページをみると、.Net Framework 4.0の場合<br /><blockquote>Windows 7, Windows Vista SP1 以降, Windows Server 2008 (Server Core 
はサポート対象外), Windows Server 2008 R2 (SP1 以降で Server Core をサポート), Windows 
Server 2003 SP2<br /></blockquote>.Net Framework 3.5 では<br /><blockquote>Windows Vista, Windows XP SP2, Windows Server 2003<br /></blockquote>となっています。Windows XP SP3 では、どちらにも当てはまらないためSHA256が使うことができないのです。ちなみにWindows XP SP2＋.Net Framework 3.5 の場合は動く模様です。見事な落とし穴です。<br /><br />幸い、<a href="http://techwing.wordpress.com/2010/10/16/xp%E7%92%B0%E5%A2%83%E3%81%A7%E3%81%AEsha256%E2%80%A6sha384%E2%80%A6sha512cryptoserviceprovider%E3%81%AE%E4%BD%BF%E7%94%A8/">こちらの方が対応策を書いています</a>ので、場合によってはレジストリをいじって回避するというのもありです。ただし、当然ランタイム環境で気にしなければならないのは確かですけどね。<br />]]>
        <![CDATA[<br />]]>
    </content>
</entry>

<entry>
    <title>mountしたNFSv4上のファイルに対してchownをした際の挙動</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/02/nfsv4mount-chwon-error.html" />
    <id>tag:labs.timedia.co.jp,2011://3.232</id>

    <published>2012-02-27T01:26:06Z</published>
    <updated>2012-02-27T08:18:51Z</updated>

    <summary>私は基本的にプログラマでインフラは専門ではありませんが、開発環境の構築など必要に応じてLinux/UNIXを触ることがあります。今回はその開発環境構築の際にはまったことを書いてみたいと思います。構築内容はSolaris10 が NFSv4の...</summary>
    <author>
        <name>SHIMANE, Yoshikazu</name>
        
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[私は基本的にプログラマでインフラは専門ではありませんが、開発環境の構築など必要に応じてLinux/UNIXを触ることがあります。今回はその開発環境構築の際にはまったことを書いてみたいと思います。<br /><br />構築内容は<br /><ul><li>Solaris10 が NFSv4のサーバとして、/export/home をexport</li><li>Debian6.0 がNFSv4クライアントとして、SolarisからexportされたディレクトリをNFSv4でマウント</li></ul>という比較的シンプルなものです。<br />Solaris10とDebianの混成とちょっと変わっていますが、今までお客様の環境はSolaris10のみで構成されていたものを、今回一部Debianに置き換えるためにこのような構成に変更となりました。つまりこの構成は未検証というものです。<br /><br />NFSは以前少しだけサーバ/クライアントともにCentOS5.xで構築したことがあり、最低限動かすだけならばそんなに難しいものではないと思っていました。ただ、今回は<br /><ul><li>サーバとクライアントでOSが異なる</li><li>そもそもDebianおよびSolaris、特にSolarisに不慣れ</li><li>/etc/passwd, /etc/shadow, /etc/group がLDAPを参照している</li></ul>という点で不安要素がありました。<br /><br />さて、実際にNFSのexport/mount を行ってみたところ問題が発生しました。<br />]]>
        <![CDATA[普通にNFSクライアントであるDebianから、Solarisのファイルの参照は問題なくできます。中身も見ることができます。が、なんとchownがうまくいかない現象に遭遇しました。今回環境移行とともに、既存のSolaris10で動いてた一部ツールをDebianに引越しますが、その中でchwonを実行している箇所があるため、これは問題です。ちなみにchwonを実行した際にエラー内容は<br /><br /><blockquote>Invalid argument<br /></blockquote>です。このエラー内容には頭の中に「？」が浮かびました。実行したコマンドは<br /><br /><blockquote># chown [username]/[groupname] filename<br /><br /></blockquote>で、LDAP経由で参照しているpasswd, group には存在しています。さて何が悪いのでしょうか？<br />この問題を解決してくれたのは同僚でした。ユーザ名、グループ名を引きに行く際、NFSv3とNFSv4とではプロトコルレイヤーで解決方法がことなることが原因ということでした。(参考のURLは失念してしまいました。すいません。)<br />ちなみに、そこのページにはNFSv4の仕様について記述があるのですが、「NFSは後方互換性はないよ！(超意訳)」とはっきり書かれていました。<br /><br />では結局どうしたかというと、あえてNFSv4を使う必要がないためDebianでNFSをマウントする際に明示的にNFSv3のプロトコルを指定するようにしました。NFSv4とNFSv3で完全な互換性はないものの、NFSv4の実装はNFSv3の実装も持っているので大抵はこれで回避できます。<br />暫定ではありますがこれで問題解決。めでたしめでたし。<br />]]>
    </content>
</entry>

<entry>
    <title>シンタックスハイライトを実装する(Ruby &amp; Parslet 編)</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/02/implement-syntax-highlighting-tool-in-ruby-with-parslet.html" />
    <id>tag:labs.timedia.co.jp,2012://3.281</id>

    <published>2012-02-15T15:00:00Z</published>
    <updated>2012-02-15T09:13:17Z</updated>

    <summary>問題 世の中にはシンタックスハイライトを行うツールが既に多数存在しています。例えば以下のようなものがあります: GNU Source-highlight (コマンドラインツール) SHJS (JavaScriptでの実装; クライアントサイ...</summary>
    <author>
        <name>kana</name>
        
    </author>
    
    <category term="heroku" label="heroku" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="parslet" label="parslet" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="peg" label="peg" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="ruby" label="ruby" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="vim" label="vim" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<h3>問題</h3>

<p>世の中にはシンタックスハイライトを行うツールが既に多数存在しています。例えば以下のようなものがあります:</p>

<ul>
<li><a href="http://www.gnu.org/software/src-highlite/">GNU Source-highlight</a> (コマンドラインツール)</li>
<li><a href="http://shjs.sourceforge.net/">SHJS</a> (JavaScriptでの実装; クライアントサイドで動的にハイライトする)</li>
<li><a href="http://alexgorbatchev.com/SyntaxHighlighter/">SyntaxHighlighter</a> (SHJSと同様)</li>
</ul>

<p>メジャーな言語やフォーマットなら標準でシンタックスハイライトの設定が同梱されていますが、
ニッチな言語やフォーマットだとまずそのような設定は存在しません。
それならば独自に設定を書けばいいのですが、
大抵のツールでは構文の定義方法が特定のパーツに該当する正規表現を並べるだけなので、
言語によっては構文の妥当な記述が不可能な場合もあります。</p>

<p>となると独自に実装せざるを得ません。
例えば
<a href="http://vim-doc.heroku.com/view?https://raw.github.com/kana/vim-arpeggio/master/doc/arpeggio.txt">Vim の :help ドキュメントを良い感じに Web ブラウザ上で見るためのツール</a>
を作って <a href="http://www.heroku.com/">Heroku</a> で動かそうと思った場合、
<a href="http://code.google.com/p/vim/source/browse/runtime/syntax/vim.vim">Vim の :help ドキュメントの構文のいい加減さ</a>
から、まず既存のツールを利用してのシンタックスハイライトはできません。
さらにこのツールの場合はリンク周りもあれこれ面倒を見る必要があるため、
ますます既存のツールの利用はできません。</p>

<p>という訳で元のソースをパースしていい感じにシンタックスハイライトする仕組みを作る必要があります。
ことパースに関して言えば <a href="http://www.ruby-lang.org/">Ruby</a> には様々な
<a href="http://rubygems.org/">gem</a> が存在しているので、そのどれかを使うことになります。
パース関連で言うと以下のような gem があるのですが:</p>

<ul>
<li><a href="https://github.com/nathansobo/treetop">treetop</a> (Lex/Yacc のように独自 DSL を Ruby のコードへコンパイルする必要がある。ダサい)</li>
<li><a href="https://github.com/mjijackson/citrus">citrus</a> (treetop と同様のダサさ)</li>
<li><a href="https://github.com/luikore/rsec">rsec</a> (Ruby 上の DSL で構文の記述を行う。でもその DSL がダサい)</li>
<li><a href="http://kschiess.github.com/parslet/">parslet</a> (Ruby 上の DSL で構文の記述を行う。 DSL が超COOOOOOOOOL。構文エラー時の出力もCOOOOOOOOOL)</li>
</ul>

<p>という感じなので parslet 一択という状態です。
そういう訳で parslet を使って Ruby でシンタックスハイライトを実装してみましょう。</p>
]]>
        <![CDATA[<h3>実装</h3>

<h4>独自のパーサーの定義</h4>

<pre><code>require 'parslet'

class VimHelpParser &lt; Parslet::Parser
  # TODO: ここにパースのルールをいろいろ書こう!
end
</code></pre>

<h4>パースのルールの定義: <code>rule</code></h4>

<pre><code># 「指定した文字列が来る」形は str を使う。
rule(:rule_name) {
  # TODO: ここに入力規則を書こう!
}
</code></pre>

<h4>固定の文字列にマッチさせる: <code>str</code></h4>

<pre><code>rule(:note) {
  str('NOTE')
}
</code></pre>

<h4>ある範囲の文字にマッチさせる: <code>match</code></h4>

<pre><code>rule(:space) {
  match('[ \t]')
}
</code></pre>

<ul>
<li>1文字分に相当する正規表現しか記述できないので注意。</li>
<li><code>match('[a-z]+')</code> などとは書けない。</li>
<li><code>match('[a-z]').repeat(1)</code> と書く。</li>
</ul>

<h4>「aの次にbが来る」を表す: <code>&gt;&gt;</code></h4>

<pre><code>rule(:vimscript_link) {
  str('vimscript#') &gt;&gt;
  match('[0-9]')
}
</code></pre>

<h4>「aが繰り返し現れる」を表す: <code>repeat</code></h4>

<pre><code>rule(:vimscript_link) {
  str('vimscript#') &gt;&gt;
  match('[0-9]').repeat(1)
}
</code></pre>

<ul>
<li>最初の引数は最低繰り返し回数。省略すると0。</li>
<li><code>match('[0-9]').repeat(1, 3)</code> のように最大繰り返し回数も指定可能。</li>
</ul>

<h4>マッチしたパーツに名前を付ける: <code>as</code></h4>

<pre><code>rule(:vimscript_link) {
  (
    str('vimscript#') &gt;&gt;
    match('[0-9]').repeat(1).as(:id)
  ).as(:vimscript_link)
}
</code></pre>

<ul>
<li>この名前は後でパース結果を処理する際に使います。</li>
</ul>

<h4>「aまたはbが現れる」を表す: <code>|</code></h4>

<pre><code>rule(:special_key) {
  str('CTRL-') &gt;&gt;
  (
    str('{char}') |
    match('[A-Za-z0-9]').repeat(1) |
    match('.')
  )
}
</code></pre>

<h4>「任意の1文字」を表す: <code>any</code></h4>

<pre><code>rule(:special_key) {
  str('CTRL-') &gt;&gt;
  (
    str('{char}') |
    match('[A-Za-z0-9]').repeat(1) |
    any
  )
}
</code></pre>

<ul>
<li><code>match('.')</code> でも同じ意味ですが、 <code>any</code> の方が読み易いです。</li>
</ul>

<h4>「aは省略可能」を表す: <code>maybe</code></h4>

<pre><code>rule(:spaces?) {
  match('[ \t]').repeat(1).maybe
}
</code></pre>

<ul>
<li><code>repeat(0, 1)</code> でもほぼ同じ効果が得られますが、 <code>maybe</code> の方が読み易いです。</li>
<li><code>repeat(0, 1)</code> と <code>maybe</code> だとパース結果の表現が異なります。</li>
<li>「aは省略可能」を表すなら <code>maybe</code> の方が扱い易いパース結果になるので、敢えて <code>repeat(0, 1)</code> を使うことはないと思います。</li>
</ul>

<h4>他のルールを参照する</h4>

<pre><code>rule(:spaces) {
  match('[ \t]').repeat(1)
}
rule(:spaces?) {
  spaces.maybe
}
</code></pre>

<h4>「次にaが来る」「次にaが来ない」を表す: <code>present?</code> / <code>absent?</code></h4>

<pre><code>rule(:tag_anchor) {
  star.as(:begin) &gt;&gt;
  ((space | newline | star | pipe).absent? &gt;&gt; any).
    repeat1.
    as(:tag_anchor) &gt;&gt;
  star.as(:end) &gt;&gt;
  ((space | newline).present? | any.absent?)
}
</code></pre>

<ul>
<li>入力を先読みしますが消費はしません。</li>
<li>応用例:
<ul>
<li>「a以外のもの」を表す: <code>a.abscent? &gt;&gt; any</code></li>
<li>「入力の最後まで到達した」を表す: <code>any.abscent?</code></li>
</ul></li>
</ul>

<h4>パースの開始点となるルールの指定: <code>root</code></h4>

<pre><code>root(:help)
rule(:help) {
  token.repeat
}
rule(:token) {
  header |
  option |
  tag_anchor |
  ...
}
</code></pre>

<h4>パースの実行</h4>

<pre><code>VimHelpParser.
new().
parse("*arpeggio.txt*  Vim plugin for ...")
</code></pre>

<h4>パース結果</h4>

<pre><code>class VimHelpParser &lt; Parslet::Parser
  rule(:vimscript_link) {
    (
      str('vimscript#') &gt;&gt;
      match('[0-9]').repeat(1).as(:id)
    ).as(:vimscript_link)
  }
end

VimHelpParser.new().vimscript_link.parse("vimscript#2100")
#==&gt; {:vimscript_link =&gt; {:id =&gt; '2100'}}
</code></pre>

<ul>
<li><code>str</code> や <code>match</code> の結果はマッチした文字列(に入力元での位置情報が付加されたオブジェクト)になります。</li>
<li><code>as</code> を使うと結果は <code>Hash</code> になります。キーが <code>as</code> で指定したオブジェクト(普通はシンボル)で、対応する値がパース結果になります。</li>
<li><code>repeat</code> を使うと個々のパース結果を要素に持つ <code>Array</code> になります(<code>repeat</code> されたのがただの <code>str</code> や <code>match</code> の場合は <code>Array</code> ではなくマッチした文字列になります)。</li>
<li><code>maybe</code> を使うと、該当する入力があった場合はそのパース結果がそのまま <code>maybe</code> のパース結果になります。該当する入力がなかった場合は nil が <code>maybe</code> のパース結果になります。</li>
</ul>

<h4>パース結果の変換</h4>

<pre><code>class VimHelpTransformer &lt; Parslet::Transform
  rule(:vimscript_link =&gt; {:id =&gt; simple(:id)}) {
    base_uri = 'http://www.vim.org/scripts/script.php'
    %Q[&lt;a class="vimscript_link" href="#{base_uri}?script_id=#{id.to_s}"&gt;vimscript##{id.to_s}&lt;/a&gt;]
  }
end

VimHelpTransformer.new().apply({:vimscript_link =&gt; {:id =&gt; '2100'}})
# ==&gt; %Q[&lt;a class="vimscript_link" href="http://www.vim.org/scripts/script.php?script_id=2100"&gt;vimscript#2100&lt;/a&gt;]
</code></pre>

<ul>
<li>このような感じで <code>rule(個々のパース結果を表すオブジェクト) {変換結果を導出する式}</code> を書きます。</li>
<li>「個々のパース結果を表すオブジェクト」はほぼそのままパース結果とマッチングされますが、<a href="http://kschiess.github.com/parslet/transform.html">ワイルドカード的なもの</a>を指定することができます。
<ul>
<li>ワイルドカードにマッチしたオブジェクトは適宜ローカル変数に束縛され、その状態で <code>rule</code> のブロックが実行されます。</li>
<li>例えば <code>simple(:id)</code> は <code>Array</code> でも <code>Hash</code> でもないオブジェクトにマッチします。マッチしたオブジェクトはローカル変数 <code>id</code> に束縛されます。</li>
</ul></li>
<li><code>apply</code> が受け取ったパース結果(普通はネストした <code>Hash</code>)の内容を適宜 <code>rule</code> に従って変換してくれます。</li>
</ul>

<h4>んでんでんで</h4>

<p><a href="https://github.com/kana/vim-doc/blob/69e64d6802d8bc13d55efada38a6a4f7f050ebf1/parser.rb#L181">一旦パーサーができて</a>しまえば、
あとは <a href="https://github.com/kana/vim-doc/blob/69e64d6802d8bc13d55efada38a6a4f7f050ebf1/parser.rb#L355"><code>Parslet::Transform</code> を使って各種構文を <code>span</code> 要素で括って適切な <code>class</code> 属性を付けた HTML のスニペットへ変換</a>してやり、
<a href="https://github.com/kana/vim-doc/blob/69e64d6802d8bc13d55efada38a6a4f7f050ebf1/public/stylesheets/syntax-highlighting.css">それっぽい CSS を用意</a>してあげればシンタックスハイライトのできあがりという訳です。
やりましたね。</p>

<p>parslet は非常によくできているので、ちょろっと何かをパースする必要に迫られたときでも、上記のポイントを押さえていれば何とかなるでしょう。</p>

<h3>付録</h3>

<ul>
<li><a href="http://vim-doc.heroku.com/">実際に作ったツール</a></li>
<li><a href="https://github.com/kana/vim-doc">実際に書いたソースコード一式</a> (※非常にやっつけ仕事)</li>
</ul>
]]>
    </content>
</entry>

<entry>
    <title>CentOS-6.2にPhantomJS-1.4.1をインストールする</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/02/how-to-install-phantomjs-1.4.1-on-centos-6.2.html" />
    <id>tag:labs.timedia.co.jp,2012://3.282</id>

    <published>2012-02-10T14:04:00Z</published>
    <updated>2012-02-14T09:14:40Z</updated>

    <summary>みなさん仕事でPhantomJS使っていますか？僕は使っていません。でもそろそろ使ってみたいので、仕事でよく使うCentOSにPhantomJSをインストールする方法を調べてみました。 環境 今回はVirtualBoxes - Free V...</summary>
    <author>
        <name>troter</name>
        <uri>http://troter.jp/</uri>
    </author>
    
    <category term="javascript" label="javascript" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<p>みなさん仕事で<a href="http://www.phantomjs.org/">PhantomJS</a>使っていますか？僕は使っていません。でもそろそろ使ってみたいので、仕事でよく使うCentOSにPhantomJSをインストールする方法を調べてみました。</p>

<h2>環境</h2>

<p>今回は<a href="http://virtualboxes.org/">VirtualBoxes - Free VirtualBox® Images</a>で公開されているCentOS-6.2のイメージを利用します。</p>

<ul>
<li><a href="http://virtualboxes.org/images/centos/">http://virtualboxes.org/images/centos/</a></li>
<li><a href="http://sourceforge.net/projects/virtualboximage/files/CentOS/6.2/CentOS-6.2-i386.7z">http://sourceforge.net/projects/virtualboximage/files/CentOS/6.2/CentOS-6.2-i386.7z</a></li>
</ul>

<p>PhantomJSをインストールする前に、あらかじめ次のコマンドでライブラリを更新と開発ツールのインストールを行います。依存関係などが面倒なので、開発ツールは全部インストールします。</p>

<pre><code>sudo yum upgrade
sudo yum groupinstall 'Development tools' 'Additional Development'
</code></pre>
]]>
        <![CDATA[<h2>phantomjs-rpmsを利用してインストール</h2>

<p>最近のPhantomJSのインストール方法はCentOS/RHELの項が追加されていす。</p>

<ul>
<li><a href="http://code.google.com/p/phantomjs/wiki/Installation">http://code.google.com/p/phantomjs/wiki/Installation</a></li>
<li><a href="https://github.com/jbraeuer/phantomjs-rpms">https://github.com/jbraeuer/phantomjs-rpms</a></li>
</ul>

<p>公式サイトのすすめに従い、phantomjs-rpmsを使ってインストールしたいと思います。</p>

<pre><code>cd /var/tmp
git clone git://github.com/jbraeuer/phantomjs-rpms.git
cd phantomjs-rpms
</code></pre>

<h3>Qt-4.7のインストール</h3>

<p>fetch-qt-rpmsコマンドで必要なrpmをダウンロードしてインストールします。</p>

<pre><code>./fetch-qt-rpms # Qt-4.7をダウンロード
sudo yum remove qt-x11 qt phonon perl-XML-SAX-Base # CentOS6.2用のQt(4.6.2)を削除
sudo yum install RPMS/el/6/i386/* # Qt-4.7をインストール
</code></pre>

<h3>PhantomJSのビルドとインストール</h3>

<p>まず、ソースコードを取得します。今回はfetch-phantomjs-branchコマンドを使わずに取得します。</p>

<p>(現在のバージョンのphantomjs-rpmsではドキュメントの説明通り'./fetch-phantomjs-branch 1.4.1'を実行すると1.4.1ではなく1.5.0(development)のアーカイブを取得してしまうため)</p>

<pre><code># 本来ならこんな努力必要無いはず、、、
wget https://github.com/ariya/phantomjs/tarball/1.4.1 -O ariya-phantomjs-b60f101.tar.gz --no-check-certificate
tar zxf ariya-phantomjs-b60f101.tar.gz
mv ariya-phantomjs-b60f101 phantomjs-1.4.1
tar cf phantomjs-1.4.1-source.tar.gz phantomjs-1.4.1
mv phantomjs-1.4.1-source.tar.gz SOURCES/
rm -rf phantomjs-1.4.1
rm -rf ariya-phantomjs-b60f101.tar.gz
</code></pre>

<p>苦労の末アーカイブを取得しました。PhantomJSをビルドしてインストールします。</p>

<pre><code>./rpm SPECS/phantomjs-1.4.1.spec
sudo yum install RPMS/i686/phantomjs*
</code></pre>

<h2>xvfbの設定</h2>

<p>Headless WebkitなPhantomJSですが、現在のバージョンでは動作にXサーバが必須のようです。FAQではxvfbを利用する方法が紹介されています。</p>

<ul>
<li><a href="http://code.google.com/p/phantomjs/wiki/FAQ">http://code.google.com/p/phantomjs/wiki/FAQ</a></li>
<li><a href="http://code.google.com/p/phantomjs/wiki/XvfbSetup">http://code.google.com/p/phantomjs/wiki/XvfbSetup</a></li>
</ul>

<p>phantomjs-rpmsにはxvfbの為の二つのスクリプトが含まれています。</p>

<h3>SOURCES/xvfb-run.sh</h3>

<p>xvfb-run.shはxvfbを起動した上でコマンドを実行するスクリプトです。xvfb-run.shを利用すると次の様にPhantomJSを起動する事が出来ます。</p>

<pre><code>./xvfb-run.sh phantomjs --version
</code></pre>

<h3>SOURCES/xvfb.init</h3>

<p>xvfb.initはxvfbをサービスとして起動するためのスクリプトです。start-stop-daemonというdebian由来のツールに依存しています。次のエントリを参考にしてインストールしましょう。</p>

<ul>
<li><a href="http://kaihatsu.mikagamikobo.com/2010/11/start-stop-daemoncentos.html">start-stop-daemonをCentOSで使う</a></li>
</ul>

<p>xvfb.initをインストールます。</p>

<pre><code>sudo cp SOURCES/xvfb.init /etc/init.d/xvfb
sudo chmod 755 /etc/init.d/xvfb
sudo chkconfig --add xvfb
sudo chkconfig xvfb on
</code></pre>

<p>xvfbをサービスとして起動します。</p>

<pre><code>sudo /etc/init.d/xvfb start
</code></pre>

<p>この場合、次のコマンドでPhantomJSを実行する事が出来ます。</p>

<pre><code>DISPLAY=:99 phantomjs --version
</code></pre>

<h2>まとめ</h2>

<p>CentOSにRPMを使ってPhantomJSをインストールしました。これでPhantomJSを採用する場合の障壁が一つ減りましたね。いつPhantomJSでWeb魚拓を作成する案件が来ても大丈夫そうです。</p>
]]>
    </content>
</entry>

<entry>
    <title>Vim で Git diff の出力からカーソル下にある変更箇所へ移動する</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/02/go-to-the-changed-block-under-the-cursor-from-git-diff-in-vim.html" />
    <id>tag:labs.timedia.co.jp,2012://3.280</id>

    <published>2012-01-31T15:00:00Z</published>
    <updated>2012-01-19T08:27:02Z</updated>

    <summary>問題 パッチのレビューなどで Git の diff の出力を読む機会はそれなりにあると思います。 その際、 diff で列挙されている内容だけでなく前後のコードも確認するために変更のあったファイルを開くことも多々あるでしょう。 Vim には...</summary>
    <author>
        <name>kana</name>
        
    </author>
    
    <category term="editorwar" label="editorwar" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="vim" label="vim" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<h3>問題</h3>

<p>パッチのレビューなどで
<a href="http://git-scm.com/">Git</a>
の diff の出力を読む機会はそれなりにあると思います。
その際、 diff で列挙されている内容だけでなく前後のコードも確認するために変更のあったファイルを開くことも多々あるでしょう。</p>

<p><a href="http://www.vim.org/">Vim</a>
にはこの状況にぴったりのコマンド
<a href="http://vimdoc.sourceforge.net/htmldoc/editing.html#gf"><code>gf</code></a>
があります。
<code>gf</code> はカーソル下にあるテキストからファイル名らしき文字列を探してそれを開くというコマンドです。
diff の出力には変更のあったファイルのパスが含まれていますから、
そこへカーソルを移動して <code>gf</code> を使えば良いというわけです。</p>

<p><code>gf</code> はとても便利なコマンドではあるものの、
上記の操作を何度か行っていると不満が募ってきます。
というのも、以下のような手間があるからです:</p>

<ul>
<li><code>gf</code> を実行するためにパスの書かれている位置までカーソルを移動しなければならない。</li>
<li><code>gf</code> でファイルを開いた後、レビューしたい場所までカーソルを移動しなければならない。</li>
</ul>

<p>例えばカレントバッファに以下の内容が含まれているとしましょう
(左端の数字は行番号なので適宜無視してください):</p>

<pre><code> 1 diff --git a/autoload/gf/diff.vim b/autoload/gf/diff.vim
 2 index 469fdb3..b135316 100644
 3 --- a/autoload/gf/diff.vim
 4 +++ b/autoload/gf/diff.vim
 5 @@ -21,7 +22,7 @@
 6  "     SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 7  "
 8  " Interface
 9 -function! gf#diff#go_to_hunk(type)
10 +function! gf#diff#go(type)
11    let d = gf#diff#investigate_the_hunk_under_the_cursor()
12    if d is 0
13      echomsg 'There is no diff hunk to jump.'
14 @@ -113,7 +114,7 @@ function! gf#diff#investigate_the_hunk_under_the_c
15        return 0
16      endif
17      let [d.from_path, d.to_path] = xs
18 +  call setpos('.', original_position)
19 -  call setpos(original_position)
20
21    return d
22  endfunction
</code></pre>

<p>このとき:</p>

<ul>
<li>12行目で <code>gf</code> をすると <code>autoload/gf/diff.vim</code> の25行目まで移動する。</li>
<li>16行目で <code>gf</code> をすると <code>autoload/gf/diff.vim</code> の117行目まで移動する。</li>
</ul>

<p>のような感じで <em>手作業によるカーソル移動なしに目的の位置へ移動</em> できればとても便利です。
このように <code>gf</code> の動作を拡張するにはどうすれば良いでしょうか。</p>
]]>
        <![CDATA[<h3>解答</h3>

<p><a href="https://github.com/kana/vim-gf-diff">vim-gf-diff</a> を使います。
このプラグインをインストールすると <code>gf</code> や <code>&lt;C-w&gt;f</code> などのコマンドの動作が以下のように拡張されます:</p>

<ul>
<li>カーソル下にファイル名らしき文字列がある場合:
そのファイルを開きます(Vimのデフォルトの挙動)。</li>
<li>カーソル下にファイル名らしき文字列はないが Git の diff の出力らしきテキストがある場合:
diff で示されるファイルを開いて該当する変更箇所までカーソルを移動します。</li>
</ul>

<p>これでレビューのタスクが山積みになっているときでも安心です。
やりましたね。</p>

<h3>補足</h3>

<ul>
<li>過去に<a href="http://labs.timedia.co.jp/2011/04/git-diff-aware-gf-commands-for-vim.html">Vimのgfコマンドをgit diff特有の出力でも上手く扱うようにする</a>設定例を紹介しましたが、今回紹介した vim-gf-diff は「変更箇所までカーソルを移動してくれる」「カーソル下にパス名がなくても使える」という点でさらに便利になっています。</li>
<li>今回のように「カーソル周辺のテキスト等を元に適切なファイルを開く」というケースは他にもあると思われるので、vim-gf-diff と同様の拡張が簡単に書けるよう <a href="https://github.com/kana/vim-gf-user">vim-gf-user</a> というライブラリも作りました。こちらも参考にしてください。</li>
<li>vim-gf-diff を使う場合は vim-gf-user も合わせてインストールしてください(vim-gf-diff が vim-gf-user を利用して作られているため)。</li>
<li>次回は Emacs 編です。</li>
</ul>
]]>
    </content>
</entry>

<entry>
    <title>Vimでカーソル行のテキストを簡単に選択/処理する</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2012/01/vim-textobj-line.html" />
    <id>tag:labs.timedia.co.jp,2012://3.279</id>

    <published>2012-01-17T08:50:09Z</published>
    <updated>2012-01-17T08:54:32Z</updated>

    <summary>問題 世間一般のエディタではカーソルを行頭や行末に移動するキーが C-a だったり C-e だったり Home だったり End だったりと、 それなりに押下し易い配置になっているのですが、 Vim では何を思ったのか ^ と $ という謎...</summary>
    <author>
        <name>kana</name>
        
    </author>
    
    <category term="editorwar" label="editorwar" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="vim" label="vim" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<h3>問題</h3>

<p>世間一般のエディタではカーソルを行頭や行末に移動するキーが
<code>C-a</code> だったり <code>C-e</code> だったり <code>Home</code> だったり <code>End</code> だったりと、
それなりに押下し易い配置になっているのですが、
<a href="http://www.vim.org/"><code>Vim</code></a> では何を思ったのか <code>^</code> と <code>$</code> という謎のキー割り当てになっています。
この<a href="http://whileimautomaton.net/2008/12/15185341">謎のキー割り当てにはそれなりの理由があると思われる</a>のですが、
時々不便に思う場合があります。</p>

<p>例えば「カーソル行のテキストをコピーして他のアプリケーションにペーストする」というシチュエーションを考えてみましょう。
コピー自体は <code>"*yy</code> ですぐできるのですが、これでは改行文字が含まれるため、ペーストした際に<a href="http://gyazo.com/ba300c59110ce80b1724a673dac5085e">悲しい結果</a>を招くことが多々あります。
<code>^vg_"*y</code> や <code>0v$h"*y</code> とすれば改行文字抜きでコピーはできるものの、
キー押下難易度の高さにストレスが溜まってしまいます。
どうにかして快適にカーソル行のテキストを選択/処理できないものでしょうか。</p>
]]>
        <![CDATA[<h3>解答</h3>

<p><a href="https://github.com/kana/vim-textobj-line">vim-textobj-line</a> を使います。
このプラグインをインストールすると</p>

<ul>
<li><code>^vg_"*y</code> と同じことが <code>vil"*y</code> や <code>"*yil</code> で</li>
<li><code>0v$h"*y</code> と同じことが <code>val"*y</code> や <code>"*yal</code> で</li>
</ul>

<p>できるようになります。</p>

<p>単にこれだけの代物ですが、あるとないとでは快適度合が段違いです。</p>

<h3>余談</h3>

<p>Vim を使い始めて今年で10周年ほどになりますが、
<a href="http://vimdoc.sourceforge.net/htmldoc/motion.html#g_"><code>g_</code></a>
の存在は vim-textobj-line を書いている最中に初めて知りました。</p>

<p>次回は Emacs 編です。</p>
]]>
    </content>
</entry>

<entry>
    <title>Rubyistよ、irbを捨ててPryを使おう</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2011/12/rubyist-should-use-pry.html" />
    <id>tag:labs.timedia.co.jp,2011://3.277</id>

    <published>2011-12-26T01:30:00Z</published>
    <updated>2011-12-27T01:42:38Z</updated>

    <summary>Pryは結構前からgithubのリポジトリを追いかけている人達には認知されていましたが、RailsCastsでも紹介されたことから、Ruby界で一気に広がりを見せています。 ちなみに発音はpra&apos;i(ぷらい)です。英単語で「覗く」などを意味...</summary>
    <author>
        <name>yoppi</name>
        <uri>http://twitter.com/yoppiblog/</uri>
    </author>
    
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<p><a href="http://pry.github.com/">Pry</a>は結構前からgithubのリポジトリを追いかけている人達には認知されていましたが、RailsCastsでも紹介されたことから、Ruby界で一気に広がりを見せています。
ちなみに発音は<code>pra'i</code>(ぷらい)です。英単語で「覗く」などを意味します。</p>

<p>今回はそんな便利なPryについて少し紹介したいと思います。</p>
]]>
        <![CDATA[<h3>Pryはirbの代わりになるREPL</h3>

<p>Pryを一言で説明すると、irbと同様にREPL環境を提供してくれます。
では、さっそくインストールしてみましょう。</p>

<pre><code>$ gem install pry pry-doc
</code></pre>

<p>さて、これでインストールできました。Pryを起動しましょう。</p>

<pre><code>$ pry
[1] pry(main)&gt;
</code></pre>

<p>なんの変哲もないプロンプトですね。irb>からpry>に変わっただけです。
では、何か計算させてみましょうか。</p>

<pre><code>[2] pry(main)&gt; -&gt;n{ i=0;j=1;n.times{j=i+i=j};i }.call(10)
=&gt; 55
</code></pre>

<p>お気づきでしょうか? 式を評価した結果が色づけされていますよね。
irbでは評価した式の値を色づけする場合、wieble等、他のgemを使う必要がありましたが、Pryではデフォルトで色づけされています。
さらに設定ファイルから、自分好みの色に設定できます。</p>

<p>次はメソッドを書いてみましょう。</p>

<pre><code>[3] pry(main)&gt; def foo
[3] pry(main)*   ^
</code></pre>

<p>メソッドの定義を書いて改行すると自動でインデントされることがわかります。大変便利です。
もちろん、今まで通りirbと同じことがそのまま実現できます。</p>

<h3>shellとの統合</h3>

<p>Pryはshellと統合し、shellのコマンドをPryコンソール上で実行できます。
ただ、コマンドの前に'.'を付けて実行します。</p>

<pre><code>[1] pry(main)&gt; .ls
[2] pry(main)&gt; .pwd
[3] pry(main)&gt; .git log --pretty=oneline
</code></pre>

<p>従来irbでは<code>system()</code>を使って評価していましたが、統合されたことにより煩わしさから解放されています。
また、統合されていることにより、次のようにRubyの#{}も評価して式展開してくれます。</p>

<pre><code>[4] pry(main)&gt; x = "class Hoge"
[5] pry(main)&gt; .find . -name "*.rb" | xargs grep #{x}
</code></pre>

<p>組み込みコマンドの<code>shell-mode</code>を使うと、プロンプトにカレントディレクトリが表示され、tabキーでディレクトリ名を補完できるようになり、よりファイル操作が簡単になります。</p>

<pre><code>[6] pry(main)&gt; shell-mode
pry main:/Users/yoppi $ shell-mode
[8] pry(main)&gt;
</code></pre>

<p>shell-modeを抜けるには、再度<code>shell-mode</code>コマンドを実行します。</p>

<h3>組み込みコマンド</h3>

<p>Pryにはいくつか組み込みコマンドが用意されています。
コマンドの一覧を見るにはPryコンソール上で<code>help</code>コマンドを実行してみましょう。</p>

<pre><code>[1] pry(main)&gt; help
</code></pre>

<p>以下に便利な組み込みコマンドの一部を紹介します。</p>

<ul>
<li>hist: Pryコンソールで評価した過去の式の一覧を確認できます</li>
<li>ls: 現在のフレームで有効なオブジェクトを表示します。'デバッガとして使う'で詳しく紹介します</li>
<li>gem-install、gem-list: Pryコンソール上でgemをインストールしたり、gemの一覧を確認できます</li>
<li>gist-method: gemのgistをさらにラップしたものが使えます</li>
<li>shell-mode: Pryからシームレスにファイルにアクセスでき、Pryからファイルを操作したい場合はshell-modeになると便利です</li>
<li>!: Pryで評価しているフレームをリセットします</li>
<li>ri: riコマンドをPry上で実行します</li>
<li>show-doc: 対象メソッドのドキュメントを表示します</li>
<li>show-method: 対象メソッドの実装を表示します</li>
</ul>

<p>やはりよく使うコマンドは<code>hist</code>と<code>ls</code>でしょうか。</p>

<h3>オブジェクトを調査する</h3>

<p>Pry独自の概念として、オブジェクト間を移動できます。
デバッガのフレームに似ています。
lsコマンドで現在のオブジェクトの一覧を表示し、cdコマンドでそのオブジェクトに移動できます。</p>

<pre><code>[1] pry(main)&gt; a = "foo"
[2] pry(main)&gt; ls
locals: _  _dir_  _ex_  _file_  _in_  _out_  _pry_  a  version
[3] pry(main)&gt; cd a
[4] pry("foo"):1&gt; nesting
Nesting status:
--
0. main (Pry top level)
1. "foo"
[5] pry("foo"):1&gt; ls
Comparable methods: &lt; &lt;= &gt; &gt;= between?
String methods: ... 
[6] pry("foo"):1&gt; upcase
=&gt; "FOO"
</code></pre>

<p>この機能のおかげで、とある深くネストしたオブジェクトの調査もcdして潜っていけば、調査する範囲を狭めることができるので大変便利ですね。</p>

<h3>簡易デバッガとして使う</h3>

<p>Rubyのコードを書いていてある程度の量になってくると、個々のモジュールはRSpecによるユニットテストにがっちり守られていても、やはり、ソフトウェアを開発する以上デバッガの恩恵を受けたいものです。
往々にして、個々のモジュールを結合したときに、予想できなかった問題が発生するものだからです。
原因をすばやく追及するために、デバッガはプログラマにとって必要不可欠なツールでしょう。
実は、Pryの真の機能はREPLではなく、この先ほどのオブジェクトの調査機能にあるようにデバッガとしての機能によるものが多いです。</p>

<p>では、例としてRailsアプリを作っているときにデバッガで追いかけたいとしましょう。
適当なコントローラのアクションで次のコードを差し込みましょう。</p>

<pre><code>binding.pry
</code></pre>

<p>そうすると、ここがブレークポイントになり、Pryコンソールが立ち上がります。
つまり自分でbinding.pryを評価する式を書くので、その式を評価するかどうかは、プログラマが自由に決定できるので、
条件付きブレークポイントを自由に書けることになります。</p>

<pre><code>binding.pry if expression
</code></pre>

<p>さて、これでRailsを起動して  アプリケーションを実行してみましょう。
binding.pryを書いたところで停止するはずです。
停止すると同時にPryコンソールが起動します。
まさにデバッガのように前後のコードが表示されつつ停止していることがわかるでしょう。
停止した時点で評価されたオブジェクトにアクセスできるので、デバッグを自由に進められます。
ステップ実行したければ、<code>binding.pry</code>を停止させたい箇所に埋め込みましょう。
Railsはconrollerに変更があれば再ロードするのでstep実行も簡単ですね。</p>

<p>普通のRubyアプリケーションであれば、<code>edit-method</code>コマンドで現在のメソッド名を指定することでそのメソッドを編集でき、また、直接エディタで編集した場合<code>reload-method</code>で読み込みなおすとstep実行できます。</p>

<h3>ドキュメントに素早く参照できる</h3>

<p>show-method、stat等のコマンドが用意されています。
また、シェル経由でriコマンドをそのまま使用できます。
VimやEmacs使い達は、それぞれのエディタ上で素早くドキュメントを牽けるようにしているはずですが、irbで作業しているときには牽けません。
Pryではこれらの組み込みコマンドが提供されていることで、素早くドキュメントにアクセスできます</p>

<pre><code>[1] pry(main)&gt; ri Array#sample
[2] pry(main)&gt; require 'pathname'
[3] pry(main)&gt; show-doc Pathname#children
</code></pre>

<h3>gemやCの実装も読める</h3>

<p>さて、Rubyのオブジェクトに対してメソッドを呼び出すわけですが、そのオブジェクトがどう実装されているか気になるときがあります。
特に、gemライブラリを使っているときに、APIがどんなことをしているのか素早く知りたいわけです。</p>

<pre><code>[4] pry(main)&gt; require 'nokogiri'
[5] pry(main)&gt; show-method Nokogiri::HTML::Document.parse
From: /Users/yoppi/opt/local/ruby/ruby-1.9.3-p0/lib/ruby/gems/1.9.1/gems/nokogiri-1.4.4/lib/nokogiri/html/document.rb @ line 64:
Number of lines: 22
Owner: #&lt;Class:Nokogiri::HTML::Document&gt;
Visibility: public

def parse string_or_io, url = nil, encoding = nil, options = XML::ParseOptions::DEFAULT_HTML
...
</code></pre>

<p>また、Rubyの組み込みライブラリはCで実装されています。
よくRubyiest達はCで実装しているコードを眺めて、実装を楽しんだり、もっと改善できるところはなかな? と考えるときがあります。
Pryなら簡単に該当する組み込みライブラリのCのコードを読めます。
Cのコードを読むには、<code>pry-doc</code>をインストールしておく必要があります。
たとえば、Array#sampleは同様に</p>

<pre><code>[6] pry(main)&gt; show-method Array#sample
static VALUE
rb_ary_sample(int argc, VALUE *argv, VALUE ary)
{
    VALUE nv, result, *ptr;
    long n, len, i, j, k, idx[10];
...
</code></pre>

<p>と、<code>show-method</code>コマンドで牽くだけです。
これでC実装を素早く読めるので今まで実装を読まなかった人も読むようになり、Rubyの開発も活発になりそうです。
大変便利ですね。</p>

<h3>Pryをカスタマイズする</h3>

<p>さて、ここまでデフォルトの設定でPryを触ってきましたが、カスタマイズしてより便利にしましょう。
Pryのカスタマイズは、irbでは<code>~/.irbrc</code>で設定していたように、Pryも<code>~/.pryrc</code>ファイルに設定します。
<a href="https://github.com/pry/pry/wiki/Customization-and-configuration">Pry-wiki Customizing Pry</a>で詳しい説明があります。
ここではデフォルト設定されているもの以外で、知っておくと便利な機能を紹介します。</p>

<h4>コマンドのprefix</h4>

<p>組み込みコマンドに対してprefixを設定できます。この記事では直接コマンドを実行していましたよね。
しかし、そのコマンド名を変数名に使いたい場合があると困ることになります。
そこで、prefixを設定することで競合を避けられます。</p>

<pre><code>Pry.config.command_prefix = "%"
</code></pre>

<p>と設定すると、コマンドを実行するときには'%'を付けて実行しなければ評価されないようになります。</p>

<pre><code>[1] pry (main)&gt; ls
NameError: undefined local variable or method `ls' for main:Object
[2] pry (main)&gt; %ls
locals: _  _dir_  _ex_  _file_  _in_  _out_  _pry_  a  version
</code></pre>

<h4>プロンプトの設定</h4>

<p>僕は常にいくつかのRubyの版を切り替えて使っているので、irbを使用していたときもプロンプトにRubyのバージョンを表示させていました。
Pryでもプロンプトを柔軟にカスタマイズできるようになっています。
デフォルトのプロンプトは次のように設定されています。</p>

<pre><code>DEFAULT_PROMPT = [
                proc { |target_self, nest_level, pry|
                  if nest_level == 0
                    "[#{pry.input_array.size}] pry(#{Pry.view_clip(target_self)})&gt; "
                  else
                    "[#{pry.input_array.size}] pry(#{Pry.view_clip(target_self)}):#{nest_level}&gt; "
                  end
                },

                proc { |target_self, nest_level, pry|
                  if nest_level == 0
                    "[#{pry.input_array.size}] pry(#{Pry.view_clip(target_self)})* "
                  else
                    "[#{pry.input_array.size}] pry(#{Pry.view_clip(target_self)}):#{nest_level}* "
                  end
                }
               ]
</code></pre>

<p>ではデフォルトのプロンプトに加えて、Rubyの版を表示させるように設定してみましょう。</p>

<pre><code>Pry.config.prompt = [
  proc {|target_self, nest_level, pry|
    nested = (nest_level.zero?) ? '' : ":#{nest_level}" 
    "[#{pry.input_array.size}] #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}(#{Pry.view_clip(target_self)})#{nested}&gt; "
  },
  proc {|target_self, nest_level, pry|
    nested = (nest_level.zero?) ?  '' : ":#{nest_level}"
    "[#{pry.input_array.size}] #{RUBY_VERSION}-p#{RUBY_PATCHLEVEL}(#{Pry.view_clip(target_self)})#{nested}* "
  }
]
</code></pre>

<p>pryを起動すると、</p>

<pre><code>$ pry
[1] 1.9.3-p0(main)&gt;
</code></pre>

<p>Rubyの版が表示されてます。やりましたね。</p>

<h3>参考文献</h3>

<p>RailsCastsのビデオを一度視聴してみてください。Pryの使い方が一望できますし、説明もわかりやすいです。</p>

<ul>
<li><a href="http://railscasts.com/episodes/280-pry-with-rails">#280 Pry with Rails - RailsCasts</a></li>
</ul>

<p>より深く使いこなすにはドキュメントには一度目を通しましょう。ここで紹介してない機能もあります。</p>

<ul>
<li><a href="https://github.com/pry/pry/wiki">Pry wiki</a></li>
</ul>
]]>
    </content>
</entry>

<entry>
    <title>Reactive Extensions を使ってコナミコマンドを実装する</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2011/12/konami-code-with-reactive-extensions.html" />
    <id>tag:labs.timedia.co.jp,2011://3.274</id>

    <published>2011-12-15T15:00:00Z</published>
    <updated>2011-12-14T03:08:10Z</updated>

    <summary>問題 Reactive Extensions で非同期処理を簡潔に記述する では「キー入力に応じて補完候補を表示する」「ただし補完候補はAjaxで非同期に取得する」という いまどきのWebアプリケーションにならあって当然の機能が、 Reac...</summary>
    <author>
        <name>kana</name>
        
    </author>
    
    <category term="c" label="c#" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="javascript" label="javascript" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="reactiveextensions" label="reactiveextensions" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<h3>問題</h3>

<p><a href="http://labs.timedia.co.jp/2011/11/hello-reactive-extensions.html">Reactive Extensions で非同期処理を簡潔に記述する</a>
では「キー入力に応じて補完候補を表示する」「ただし補完候補はAjaxで非同期に取得する」という
いまどきのWebアプリケーションにならあって当然の機能が、
<a href="http://msdn.microsoft.com/en-us/data/gg577609">Reactive Extensions (Rx)</a>
を使うことであたかも普通のリスト処理のように記述できることを示しました。</p>

<p>入力補完は例としては単純で分かり易いものの、
もう少し別の例も欲しいところです。
という訳で、 Rx を使うことで
<a href="http://ja.wikipedia.org/wiki/コナミコマンド">コナミコマンド</a>
を実装してみましょう。</p>
]]>
        <![CDATA[<h3><a href="http://jsdo.it/kana1/nrTf">回答1: Rx を使わない場合</a></h3>

<pre><code>var lastKeyCodes = [];
var validKeyCodes = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
$(window).keydown(function (e) {
  lastKeyCodes.push(e.keyCode);
  if (validKeyCodes.length &lt; lastKeyCodes.length)
    lastKeyCodes.shift();
  if (lastKeyCodes.toString() == validKeyCodes.toString())
    alert('***!');
});
</code></pre>

<p>「最新のキー入力10個がコナミコマンドに合致するなら」という考えで書いてみました。
まあこんなものでしょう。</p>

<h3><a href="http://jsdo.it/kana1/auhl">回答2: Rx をなんとなく使った場合</a></h3>

<pre><code>var lastKeyCodes = [];
var validKeyCodes = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
var konamiStream =
  $(window)
  .toObservable('keydown')
  .Select(function (e) {return e.keyCode;});
  .Select(function (c) {
    lastKeyCodes.push(c);
    if (validKeyCodes.length &lt; lastKeyCodes.length)
      lastKeyCodes.shift();
    return lastKeyCodes.toString() == validKeyCodes.toString();
  });
konamiStream.Subscribe(function (b) {
  if (b)
    alert('***!');
});
</code></pre>

<p>回答1を直訳しました。
キー入力の処理と実際に行いたい処理を分離できているという点では良いのですが、
<code>toObservable</code> だの <code>Subscribe</code> だののために若干記述が冗長になっています。</p>

<h3><a href="http://jsdo.it/kana1/v3Vb">回答3: Rx を華麗に使った場合</a></h3>

<pre><code>var validKeyCodes = [38, 38, 40, 40, 37, 39, 37, 39, 66, 65];
var konamiStream =
  $(window)
  .toObservable('keydown')
  .Select(function (e) {return e.keyCode;});
  .BufferWithCount(validKeyCodes.length, 1)
  .Select(function (cs) {
    return cs.toString() == validKeyCodes.toString();
  });
konamiStream.Subscribe(function (b) {
  if (b)
    $('#result').prepend('&lt;div&gt;' + b + '&lt;/div&gt;');
});
</code></pre>

<p>回答1と回答2の真の問題点は最新のキー入力(<code>lastKeyCodes</code>)という状態を管理していることです。
そのために本来やりたいこと(コナミコマンドの入力判定)とは関係のないものが途中に混ざってしまい、
回りくどいコードになっています。</p>

<p>しかし
<code>BufferWithCount</code> (C# では <a href="http://msdn.microsoft.com/en-us/library/hh228968%28v=VS.103%29.aspx"><code>Buffer</code></a>)
を使えば明示的に状態を管理することなく「最新のデータn個」単位で処理を記述することができます。
これで本来やりたいことをすっきりと記述できるようになりました。
やりましたね。</p>

<h3>補足</h3>

<p><code>BufferWithCount</code> の最初の引数には一度に処理したいデータの個数を指定し、
二番目の引数では各処理の間でスキップするデータの個数を指定します。
今回の例の場合は <code>BufferWithCount(validKeyCodes.length, 1)</code> ですが、
<code>BufferWithCount(3, 3)</code> とすれば「3個単位でデータを処理する」こともできます。</p>

<p>例えば <code>xs = [1, 2, 3, 4, 5, 6, 7, ...]</code> というデータのシーケンスがあったとすると、</p>

<ul>
<li><p><code>xs.BufferWithCount(3, 1)</code> で</p>

<pre><code>`[[1, 2, 3], [2, 3, 4], ...]`
</code></pre></li>
<li><p><code>xs.BufferWithCount(3, 3)</code> で</p>

<pre><code>`[[1, 2, 3], [4, 5, 6], ...]`
</code></pre></li>
</ul>

<p>というシーケンスに変換できるということです。</p>

<p><a href="http://msdn.microsoft.com/en-us/library/system.reactive.linq.observable%28v=vs.103%29.aspx">Rx には他にも便利なメソッドが山のようにある</a>ので、
これを駆使すればより複雑な処理も簡潔に書けるようになるでしょう。</p>
]]>
    </content>
</entry>

<entry>
    <title>シェルのワンライナーの再利用性を高めるたった一つの方法</title>
    <link rel="alternate" type="text/html" href="http://labs.timedia.co.jp/2011/12/improve-reusability-of-shells-command-line-history.html" />
    <id>tag:labs.timedia.co.jp,2011://3.275</id>

    <published>2011-11-30T15:00:00Z</published>
    <updated>2011-11-30T10:21:35Z</updated>

    <summary>問題 シェルはお友達です。 一見すると役に立たないように思えるコマンドでも、 組み合わせ次第で複雑な処理をこなすための道具になります。 例えば head - ファイルの先頭10行を出力する。 cut - ファイルの各行のうち特定の部分を選ん...</summary>
    <author>
        <name>kana</name>
        
    </author>
    
    <category term="shell" label="shell" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="ja" xml:base="http://labs.timedia.co.jp/">
        <![CDATA[<h3>問題</h3>

<p>シェルはお友達です。
一見すると役に立たないように思えるコマンドでも、
組み合わせ次第で複雑な処理をこなすための道具になります。</p>

<p>例えば</p>

<ul>
<li><code>head</code> - ファイルの先頭10行を出力する。</li>
<li><code>cut</code> - ファイルの各行のうち特定の部分を選んで出力する。</li>
<li><code>shasum</code> - SHA-1 ハッシュ値を出力する。</li>
</ul>

<p>という、一つ一つでは大して役に立ちそうにないコマンドも、</p>

<pre><code> head /dev/urandom | shasum | cut -f 1 -d ' '
</code></pre>

<p>このように組み合わせることで「ランダムなパスワードを自動生成する」という偉業を達成することができます。</p>

<p>シェルをある程度使っていると上記のようなワンライナーをしばしば入力することがあります。
覚え易いものや短いワンライナーなら即席で入力しても構わないのですが、
先ほどの例のようなものになると少々入力するのが面倒です。
そこで役に立つのがコマンドラインの入力履歴です。
入力履歴があれば、例えば
<a href="http://labs.timedia.co.jp/2011/08/git-undo-999.html">三か月前に試行錯誤の末に編み出した <code>git filter-branch</code> でリポジトリを消毒するワンライナー</a>
であっても、簡単に再実行することができます。</p>

<p>入力履歴は大変便利なのですが、
こと検索においては欠点があります。
コマンド一つ一つが汎用的で小粒なために、
<em>いざ検索しようとすると適切なキーワードが閃きづらい</em> ということです。
パスワード生成の例では　<code>shasum</code> が比較的出現頻度の低いコマンドなので、
これをキーワードにして検索すればまだ見つけ易い方ではありますが、
<code>shasum</code> を含む応用例は他にもあるため、
一発で目的のワンライナーに辿り着けることは多くありません。
素早く目的のワンライナーを見つけ出すにはどうすればよいのでしょうか。</p>
]]>
        <![CDATA[<h3>解答</h3>

<p><em>ワンライナーを実行する際にタグ代わりにコメントを添えます。</em></p>

<p>シェルスクリプトを書く場合は適宜コメントを書きますが、
対話的にコマンドを入力する場合でもコメントを書くことは可能です。
例えば以下のようなワンライナーを実行しても、最後の <code>#password</code> はコメントなので単に無視されます:</p>

<pre><code>head /dev/urandom | shasum | cut -f 1 -d ' '  #password
</code></pre>

<p>このような形でワンライナーを実行して入力履歴に保存しておけば、
このコメントをキーにして即座に目的のワンライナーを探し出すことができます。
対話的にシェルを利用する場合に敢えてコメントを書くケースはまずないでしょうし、
コマンドに対する引数として <code>'#foo'</code> のようなものを指定するケースもごく稀でしょうから、
かなりの高精度で検索が可能です。</p>

<h3>補足</h3>

<p>実際には対話シェルでコメントが使えるかどうかは設定によります。</p>

<ul>
<li><a href="http://www.gnu.org/s/bash/manual/html_node/Comments.html">bash は対話シェルでのコメントはデフォルトで利用可能</a>です。
明示的に有効にするならば <code>shopt -s interactive_comments</code> で設定することができます。</li>
<li><a href="http://zsh.sourceforge.net/Doc/Release/Options.html#index-INTERACTIVE_005fCOMMENTS">zsh は対話シェルでのコメントはデフォルトで利用不可</a>です。
明示的に <code>setopt interactive_comments</code> で有効化する必要があります。</li>
</ul>

<p>また、入力履歴を有効活用する場合は記録されるコマンド数の上限をなるべく高くしておくとよいでしょう:</p>

<pre>
HISTSIZE=1000000
HISTFILESIZE=$HISTSIZE  # bash の場合
SAVEHIST=$HISTSIZE  # zsh の場合
</pre>
]]>
    </content>
</entry>

</feed>

