2009-01-08
githubでforkしたリポジトリから本家にpush
昨日いっていた問題が解決したので,あらためてgithubでforkしたリポジトリから本家にpushする方法.
本家にコミット権があるのが前提なので,ふつうは本家をcloneして作業すれば問題ないです.ただ,途中までforkで開発してたんだけど,ある日,コミット権をもらったりして本家に反映したいような時には便利です.
以下folkしたリポジトリのcloneのmaster branchにて,
# remote リポジトリを設定する $ git remote add jugyo git@github.com:jugyo/termtter.git $ git fetch jugyo # git pullして本家の変更を取り込む $ git pull --rebase jugyo # 変更をgit pushする $ git push jugyo
いろいろまわり道したけど,すごいやったことある,コレ.
おまけ
remote の master をもとにした別のbranchをローカル作成してたのが,昨日のはまりポイントだったみたい.ローカルのmaster branchは残しておいて,本家の変更点をmergeした上でpushしたいとかなら以下の方法が使える.
# ここはいっしょ $ git remote add jugyo git@github.com:jugyo/termtter.git $ git fetch jugyo # ローカル に本家branchを作成 $ git checkout -b jugyo-master jugyo/master # $ git merge master # push $ git pull --rebase jugyo master # 念のため $ git push jugyo jugyo-master:master # jugyo-master -> master
最後のpushの使い方がよくわかっていなかったけどman読んだらちゃんと書いてありました.単に
$ git push jugyo master
としてしまうと ローカルのmaster branchをリモート(jugyo)のmaster branchにpushするという意味になります.本来はローカルのjugyo-master branchをリモートのmaster branchにpushしたいので.
$ git push jugyo jugyo-master:master
という書き方になります.
2009-01-07
git remote add => pull => push で (non-fast forward)
termtterのコミット権をもらったので,これまでforkして使っていたローカルリポジトリに本家をremote addしてmergeすることにしたけど,なんかうまくいかない.
$ git remote add jugyo git@github.com:jugyo/termtter.git $ git fetch jugyo $ git checkout -b jugyo-master jugyo/master
として本家ブランチを作ったあと,
$ git merge master $ git pull --rebase jugyo master # 念のため $ git push jugyo master
mergeしてpushしようとすると,なぜか
To git@github.com:jugyo/termtter.git ! [rejected] master -> master (non-fast forward) error: failed to push some refs to 'git@github.com:jugyo/termtter.git'
といわれる.ちゃんとpullしてるのになんで… . なんの変更も加えずにgit push --dry-runしても(non-fast forward)なんだよな
termtterは拡張しやすくて楽しい
ターミナル上で動くtwitterクライアントであるところのtermtterを使ってみてます.(参考: System.Exit - Termtter - ターミナルエミュレータ上で動作する Twitter クライアント)
プラグインを作るのがすごく簡単で,かゆいところに手が届かなくても,すぐに自分で機能を拡張できます.とりあえず何個かプラグインを書いてみました.
group.rb
http://gist.github.com/44250.js
.termtter で
plugin 'group'
configatron.plugins.group.groups = {
:rits => %w(hakobe isano hitode909)
}
とか設定しといて.
> group rits
とかやると,現在のログをフィルタして指定したグループ(ここではrits)に属している人の発言だけを表示します.
quicklook.rb
> quicklook ID
とやるとIDで指定した発言に含まれるURLをQuickLookします.Mac OS Xでしかうごきません.まだ,いまいちな使い勝手.
プラグインが簡単に書けるしくみがあると,適切なサイズの問題が量産しまくれて楽しいですね!
2009-01-04
AquaSKK+はてなキーワード辞書を導入した
いいよいいよー,ってまわりの人が勧めてくれていたので,SKKのはてなキーワード辞書を導入してみた.
- SKK辞書の続き - subpop - subtech
- 「はてなダイアリーキーワードふりがなリスト」をSKKの辞書に変換 - znzの日記 - Rubyist
- SKKIMEインストールメモ - mayokara memo
あたりを参考にしまくるとOK.一回の辞書生成タスクに30秒くらいしかかかんないし,cronにしこんどけばいいな.
ひだまりすけっちさんろくご => ひだまりスケッチ×365 まりあほりっく => まりあ†ほりっく いんでっくす => 禁書目録 もてめん => motemen
すばらしいですね!
よくみる extern "C" {} と __cplusplus
C向けのライブラリのコードをながめていたらちょくちょく以下のようなコードをみる.
#ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* Cのコードがたくさん */ #ifdef __cplusplus } #endif /* __cplusplus */
なんだろうと思って調べてみたら.
- __cplusplus
- extern "C" { /* Cのコード */ }
- ブレースでかこまれた範囲で,リンカでの識別子の扱い方がCスタイルになる
らしい."この範囲のコードはCで書かれてるから,g++でコンパイルするときはCだとおもってよろしくしてあげてね"ってことみたい.
Cで書かれたライブラリはCで使われることもC++で使われることもあるから,こういうコードでうまくその差を吸収してあげてるんだなー.
CとかC++のコードみてると,リンカとかメモリ効率とかLL使ってると触れられないところに触れられておもろい.
2009-01-03
IO::MooseでもSlurpできるよ
JPerl Advent Calendar 2008でファイルをslurpする方法を紹介したけど,IO::Mooseっていうモジュールもあったんだねぇ.
#!/usr/bin/env perl use strict; use warnings; use Perl6::Say; use IO::Moose qw(File); my $content = IO::Moose::File->new( filename => './pl.pl' )->slurp; say $content;
といってもわざわざMooseなモジュールを使う必要はないかなぁ.モジュールがMooseで書かれてる利点はなんだろ.自分がモジュールを作るときに使えるときれいに使えるだろうけどなぁ.
2009-01-01
perldoc perlxstutを読んだときのメモ
正月番組をみながらperldoc perlxstutを読んだ.メモをとったのでせっかくだからはっつけておくよ.
ちょっとメモがはしょり気味なのと,うちの理解があやしいところがあってこころもとないですが,perlxstut読むときの参考にでもなればばば.
Example1
$ h2xs -A -n Mytest
で雛形がつくれる.生成されたMytest.xsにXSのコードを書く
値を返さないHello, WorldだとCODE:以下にprintfを書くだけでOK
void hello() CODE: printf("Hello, world!\n");
CODE: みたいな部分はXS特有の書き方.あとで展開されてCのコードになる.
$ perl Makefile.PL $ make
するとビルドされる.このとき作られるMytest.cをみるとXSから生成されたCのコードを見れる.
t/Mytest.tにコードを書いてみて実行結果を確認できる.
use Test::More tests => 9; BEGIN { use_ok('Mytest') }; Mytest::hello();
Example2
引数をとって値を返す関数をXSで定義してみる.さっき作ったMytest.xsに以下を追加.
int is_even(input) int input CODE: RETVAL = (input % 2 == 0); OUTPUT: RETVAL
inputで整数値を受け取り,RETVALに結果を代入する.RETVALはXSで容易される返り値のための変数.
OUTPUT: のところに変数を書くと返り値として使われる.
Example3
引数に渡ってきた変数自体を変更することで値を返す破壊的な関数を定義してみる.Mytest.xsに以下を追加.
void round(arg) double arg CODE: if (arg > 0.0) { arg = floor(arg + 0.5); } else if (arg < 0.0) { arg = ceil(arg - 0.5); } else { arg = 0.0; } OUTPUT: arg
このように仮引数argに代入してそのままOUTPUT:で返却すると,argで渡ってきた変数に変更が加えられる.
my $i; $i = -1.5; Mytest::round($i); is $i, -2.0; # ok
ということ.
ちなみに,XS => C変換はXSUBPPというのがやってるらしい.
TYPEMAPについて
TYPEMAPはCの型とPerlの値を自動的にマッピングする仕組み.
typemapファイルに型の対応や変換する方法が書いてある.(macportsのPerl5.8.8だと /opt/local/lib/perl5/5.8.8/ExtUtils/typemap にある)
Example4
Cライブラリのヘッダの情報にモジュールテンプレートを作る.ヘッダを準備してから.
$ h2xs -O -n Mytest2 ./Mytest2/mylib/mylib.h
のようにヘッダを引数に指定して実行.
くわえて,Cのライブラリも一緒にビルドするためのMakefile.PLの書き方の解説など.詳細は割愛.
XSのなかでデフォルトで用意されているもの以外のTYPEMAPが必要な場合は,モジュールディレクトリ直下のtypemapファイルに書く.
const char * T_PV
.xsファイルの構成
MODULE = Mytest2 PACKAGE = Mytest2
xsファイルのこの行より上は普通のCのコードが書ける.この行より下はXSのコードになる.XSのコードはxsubppコマンドでCのコードに変換される.
通常のXSでは,実際に呼び出されるCの関数はこの行より上の部分か,外部のライブラリで定義される.XSではPerlとそのCの関数のGlueだけが定義される.XSにちょくせつ関数の機能を書くのは例外的だ.
XSUBもうちょい詳細
XSはかしこいので,
double
foo(a, b, c)
int a
long b
const char *c
CODE:
RETVAL = foo(a,b,c);
OUTPUT:
RETVAL
本来このように書かないといけないところが,
double
foo(a, b, c)
int a
long b
const char *c
のように省略して書ける.
XSUBの引数についてもうちょっと
int foo(a, b) char &a char * b
XSで&aとかくと,Cの関数にaではなくaのアドレスがわたるようになる.ポインタをわたすときは*とbの間にスペースが必要なので注意.
引数スタック
生成されたCのコードからはST(n)マクロで引数を取得できる.
XSのコードで引数をOUTPUTでそのままかえすと引数自体が変更される.例えば以下のコードは,
void round(arg) double arg CODE: # do something OUTPUT: arg
次のようなCのコードに変換される.ST(0)に記録されていたargを処理したあと,ST(0)戻している.
double arg = (double)SvNV(ST(0));
# do something
sv_setnv(ST(0), (double)arg);
Example 5
Arrayを返す関数の例.次のように書くことで,関数の返り値としてArrayを返せる.
void
statfs(path)
char * path
INIT:
int i;
struct statfs buf;
PPCODE:
i = statfs(path, &buf);
if (i == 0) {
XPUSHs(sv_2mortal(newSVnv(buf.f_bavail)));
XPUSHs(sv_2mortal(newSVnv(buf.f_bfree)));
XPUSHs(sv_2mortal(newSVnv(buf.f_blocks)));
XPUSHs(sv_2mortal(newSVnv(buf.f_bsize)));
XPUSHs(sv_2mortal(newSVnv(buf.f_ffree)));
XPUSHs(sv_2mortal(newSVnv(buf.f_files)));
XPUSHs(sv_2mortal(newSVnv(buf.f_type)));
}
else {
XPUSHs(sv_2mortal(newSVnv(errno)));
}
MacOSXだとstatfs構造体がどのヘッダファイルに定義されてるかわからなくてコンパイルできなかった.
この例で新しくでてきたこと
- INITディレクティブは引数のデコード処理の直後に実行されるので変数の宣言に丁度良い
- PPCODEディレクティブは返り値の処理を自分で行うときに使う.
- 返り値をArrayで返すために値をスタックにつむにはXPUSHマクロを使う.
- 返り値スタックのSVはmortalになってる.mortalってなに?
- XPUSHマクロは呼び出されるたびにスタックを拡張するので無駄がある.EXTENDマクロで予めスタックを拡張してからPUSHsマクロを使うと効率が良い
Example6
引数にArrayのリファレンスをとって,HashのArrayのリファレンスを返す関数の例.Perlのデータ構造を操作するちょっと複雑な例.(コードは長いので割愛)
この例で新しくでてきたこと
- typemapを使わずにSV *を受けとってSV *を返してる.返してるのはArrayリファレンス一つなのでPPCODEを使う必要がない.
- 引数で受け取った値のValidationをINITでやっている.
if ((!SvROK(paths)) # リファレンスか? || (SvTYPE(SvRV(paths)) != SVt_PVAV) # Arrayのリファレンスか? || ((numpaths = av_len((AV *)SvRV(paths))) < 0)) # 値がはいってるか? { XSRETURN_UNDEF; # undefを返すマクロ }
- Arrayは内部ではAV *で表現される.PerlのArray操作関数と似たマクロが用意されてる.(av_len, av_fetch, av_push など).スタックと同様に事前にArrayを拡張しておくと効率がよくなる.
av_extend(results, numpaths);
- Hashは内部ではHV *で表現される.ArrayといっしょでPerlと似た操作用マクロが用意されている.
- リファレンスはnewRV関数で作る.引数のSV *はAV *やHV *をキャストして渡せる.逆にSvRVでリファレンスからSV *を得た時は自分で適切な型にキャストする必要がある.
Example7 (Coming Soon)
Example8 (Coming Soon)
Example9
ひらいているファイルをXSに渡す方法.
# PerlIOがちゃんと理解できていないのでいろいろあやしい.
stdio.hで定義されてるfputsをPerlで使うには,以下のように書く.
#define PERLIO_NOT_STDIO 0 #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include <stdio.h> int fputs(s, stream) char * s FILE * stream
typemapがうまくやってくれるおかげでPerlIOレイヤをうまくとおるようになってる?
じぶんでPerlIOつかう場合は以下のPerlIO_putsのようにPerlIO用の関数を使う.
typedef PerlIO * OutputStream; int perlioputs(s, stream) char * s OutputStream stream CODE: RETVAL = PerlIO_puts(stream, s); OUTPUT: RETVAL
PerlIOからFILE構造体をとりだして使うこともできる.
int perliofputs(s, stream) char * s OutputStream stream PREINIT: FILE *fp = PerlIO_findFILE(stream); CODE: if (fp != (FILE*) 0) { RETVAL = fputs(s, fp); } else { RETVAL = -1; } OUTPUT: RETVAL
まとめ
- XSまわりの仕組みがどうなっているのか,だいたいわかった
- XSはいろいろと空気を読んでやってくれるので,Cのコードはそんなにかかなくて良い.typemapすごい
- Perl内部系の話(SV, AV, HV とかのはなし)は最低限だけだったので勉強したい
あけましておめでとうございます
今年もどうぞよろしくおねがします.
去年はブログへのアウトプットもあまりできなかったので,今年は積極的にやりたいなぁ.
何かと決断が必要そうな年になりそうですが,無難な決断に陥らずチャレンジングにやりたいなぁ,とおもったりおもわなかったりします.がんばります.


