https://raw.github.com/cubicdaiya/zsh_completions/master/_scons
探したけどなかったので書いてみた。便利な分何かと複雑なzshだけど補完関数あたりは割と単純なのとサンプルが豊富なのでササッと書ける。
npmはハマりどころが多すぎて困る。
$ npm search dtl dtl A diff template library binding for node.js =cubicdaiya diff diff3 editdistance unified format plate A javascript templating language =chrisdickinson template dtl $ npm install -g $
https://github.com/cubicdaiya/node-dtl
最近、久々にJavaScriptを勉強し直してる関係でnode.jsで遊んでみたんだけど、結局C++で書いてしまった。
そんなにほかの言語のバインディング書いた経験はないけど、node.jsのバインディング書くのは結構簡単。
$ git clone https://github.com/cubicdaiya/node-dtl.git $ node-waf configure build $ node-waf install
// diff_str.js var dtl = require('dtl') var a = process.argv[2]; var b = process.argv[3]; var diff = new dtl.Diff(a, b); diff.compose(); console.log("editdistance:" + diff.editdistance()); diff.printSES(); console.log("Unified Diff:"); diff.composeUnifiedHunks(); diff.printUnifiedFormat();
$ node diff_str.js acbdeacbed acebdabbabed editdistance:6 a c +e b d -e a -c b +b +a +b e d Unified Diff: @@ -1,10 +1,12 @@ a c +e b d -e a -c b +b +a +b e d $
ちゃんと動いてるようだ。もちろん、diff template libraryとしての特徴を活かして文字列だけでなく数値の配列同士でも差分が取れる。
// diff_int_array.js var dtl = require('dtl') var a = [1,2,3]; var b = [1,2,5]; var diff = new dtl.Diff(a, b); diff.compose(); console.log("editdistance:" + diff.editdistance()); diff.printSES(); console.log("Unified Diff:"); diff.composeUnifiedHunks(); diff.printUnifiedFormat();
$ node diff_int_array.js editdistance:2 1 2 -3 +5 Unified Diff: @@ -1,3 +1,3 @@ 1 2 -3 +5 $
今更ながらSConsでもMakeと同じく「-j 」オプションで並列ビルドができること知った。なので、さっそく自分のプロダクト(dtl)で試してみた。CPUのスペックやビルド対象は以下の通り。
$ time scons scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... g++ -o Intdifftest.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp Intdifftest.cpp g++ -o Patchtest.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp Patchtest.cpp g++ -o Strdiff3test.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp Strdiff3test.cpp g++ -o Strdifftest.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp Strdifftest.cpp g++ -o dtl_test.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp dtl_test.cpp g++ -o dtl_test_common.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp dtl_test_common.cpp g++ -o dtl_test Intdifftest.o Patchtest.o Strdiff3test.o Strdifftest.o dtl_test.o dtl_test_common.o -lgtest -lpthread scons: done building targets. scons 10.17s user 0.46s system 98% cpu 10.754 total $
dtlはヘッダファイルのみで構成されている上にテンプレートをふんだんに使用しているので、規模の割には時間がかかる*1。このマシンだと10秒そこそこだが、僕のMacBookだと25〜30秒かかる。
$ time scons -j 4 scons: Reading SConscript files ... scons: done reading SConscript files. scons: Building targets ... g++ -o Intdifftest.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp Intdifftest.cpp g++ -o Patchtest.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp Patchtest.cpp g++ -o Strdiff3test.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp Strdiff3test.cpp g++ -o Strdifftest.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp Strdifftest.cpp g++ -o dtl_test.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp dtl_test.cpp g++ -o dtl_test_common.o -c -Wall -O2 -I/home/bokko/workspace/dtl/dtl-cpp dtl_test_common.cpp g++ -o dtl_test Intdifftest.o Patchtest.o Strdiff3test.o Strdifftest.o dtl_test.o dtl_test_common.o -lgtest -lpthread scons: done building targets. scons -j 4 16.26s user 0.61s system 323% cpu 5.209 total $
Boost.勉強会 #4にて発表してきました。アルゴリズムの解説については参考資料へのリンクを紹介するに留めてdtlのライブラリとしての機能の紹介に内容を絞り、若干ネタにも走りましたが、概ね好評だったようです。
Boostというか本格的なC++系の勉強会に参加するのは今回が初めてで何かと刺激になりました。次回もぜひ参加したいと思います。
発表の際、「どんな型でも差分取れる!」的なことを言ってしまったようなんですが、実際には対象要素列のコンテナがrandom access iteratorを備えている必要があります。なのでコンテナにはvector(かdeque)を使うのがよいでしょう。ソースコードにも「sequence must support random_access_iterator.」ってコメントを書いてるのですが、言うのをすっかり忘れておりました(_ _)。
要素の型については大抵の場合問題ありませんが、デフォルトでは要素の比較は==演算子によって行われるため、特別な比較をしたい場合はカスタムコンパレータを作成する必要があります。例えば、要素の比較の際にアルファベットの小文字と大文字の区別をしたくないなら以下のようなコンパレータを作成し、
class CaseInsensitive: public dtl::Compare<char> { public: bool impl(const char& a, const char& b) const { return tolower(a) == tolower(b); } };
Diffクラステンプレートのパラメータにさきほど作成したコンパレータを指定します。
std::string A("abc"); std::string B("abd"); dt::Diff< char, std::string, CaseInsensitive > diff(A, B);
https://github.com/cubicdaiya/onp
ぜひgithubにてフォーク -> 実装 -> pull requestしてください。お待ちしております。