Hatena::ブログ(Diary)

考える人, コードを書く人 このページをアンテナに追加 RSSフィード

About
 

2012-01-16

sconsコマンドのzsh補完関数を書いてみた

https://raw.github.com/cubicdaiya/zsh_completions/master/_scons


探したけどなかったので書いてみた。便利な分何かと複雑なzshだけど補完関数あたりは割と単純なのとサンプルが豊富なのでササッと書ける。

やり方がわかれば後はひたすらコマンドヘルプ写経し、引数毎に適切な補完を当てはめるのみ。

2011-05-18

node-dtlをnpmに登録しました

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
$

2011-05-15

dtlのnode.jsバインディング

https://github.com/cubicdaiya/node-dtl

最近、久々にJavaScript勉強し直してる関係でnode.jsで遊んでみたんだけど、結局C++で書いてしまった。

そんなにほかの言語のバインディング書いた経験はないけど、node.jsのバインディング書くのは結構簡単。


node-dtlのダウンロードインストール

$ git clone https://github.com/cubicdaiya/node-dtl.git 
$ node-waf configure build
$ node-waf install

node-dtlで文字列の差分を取る

// 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としての特徴を活かして文字列だけでなく数値の配列同士でも差分が取れる。

node-dtlで数値の配列の差分を取る

// 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
$

2011-03-06

SConsで並列ビルド

今更ながらSConsでもMakeと同じく「-j 」オプションで並列ビルドができること知った。なので、さっそく自分プロダクト(dtl)で試してみた。CPUスペックビルド対象は以下の通り。

「-j」オプション未使用

$ 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秒かかる。

「-j 4」でビルド

$ 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
$

というわけで普段の半分の時間ビルドできるようになった。

*1:さらにgtestもテンプレートバリバリ使ってるのでこれにリンクするだけで結構ビルドが遅くなる

2011-02-27

Boost.勉強会#4


Boost.勉強会 #4にて発表してきました。アルゴリズムの解説については参考資料へのリンクを紹介するに留めてdtlのライブラリとしての機能の紹介に内容を絞り、若干ネタにも走りましたが、概ね好評だったようです。

Boostというか本格的なC++系の勉強会に参加するのは今回が初めてで何かと刺激になりました。次回もぜひ参加したいと思います。

発表に関する捕捉

dtlで扱えるデータ型について

発表の際、「どんな型でも差分取れる!」的なことを言ってしまったようなんですが、実際には対象要素列のコンテナが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);
githubにUpされてるWuのアルゴリズムの実装言語一覧に○○○がねぇぞゴルァ ( ゚Д゚)という方へ

https://github.com/cubicdaiya/onp

ぜひgithubにてフォーク -> 実装 -> pull requestしてください。お待ちしております。

関連ページ