CoffeeScript

なぜ CoffeeScript がダメか - 冬通りに消え行く制服ガールは✖夢物語にリアルを求めない。 - subtech

僕の考えでは JavaScript ネイティブでない(けれど非同期プログラミングやネットワークの知識はある)人が、Node.js を使ってネットワークアプリケーションを書くという用途では結構使えると思う。

デバッグしづらいという点も Node と組み合わせる前提で考えれば coffee コマンドで直接実行すればいい話である。

また僕自身も小さなネットワークアプリケーションは最近は CoffeeScript で書いてて、fujiwara 氏などにメンテしてもらっているけれど、やはり彼も僕と同じようなスキル(JavaScriptネイティブでない)だから、そういう人が見て大体なんとなく理解できるものになってると感じる。

これがもし、AnyEvent で書いたコードだったらそうはいかなかっただろうなーとw

by typester / at 2012-04-03T10:07:00 / coffeescript · perl / Comment

OS X 10.7.3 から LaunchAgents の WatchPaths の仕様が変わったようだ

前から ~/Library/LaunchAgents にユーザー権限でおいた agent から root 所有のファイルを監視していたのだが、10.7.3 にアップデートしてからそれらが全く動かなくなってしまった。

しょうがないので /Library/LaunchAgents に移動し、 root でうごかすようにしたら再び動き出した。

監視してる root 所有のファイルはもちろん一般ユーザーでも読み込み可能な権限になっているのにこの制限は嫌だなぁ。

追記@

隣の席の人は同じものが全く問題なく動いているとのこと…。僕の環境が悪いのか…。

by typester / at 2012-04-02T11:36:00 / osx / Comment

tmux で pbcopy

デフォルトだと動かないのでなんか変なラッパーを挟むのがスタンダードな方法みたいですが、たまにしか使わないのにそんな無駄なことしたくないと、

# tmux
if [[ "$TMUX" != "" ]] then
    alias pbcopy="ssh 127.0.0.1 pbcopy"
    alias pbpaste="ssh 127.0.0.1 pbpaste"
fi

としてしのいでいる。僕の使用頻度だとこれで十分ぽい。

by typester / at 2012-03-27T11:39:00 / tmux · zsh / Comment

tmux + irssi + canything で Anything 風チャンネル切り替えする

irssi 環境を prgmr.com からさくら VPS に移行したついでに irssi のプラグインを見直していて、そのときに nicklist.pl というのをいれたわけですが、これがなかなか hackish な実装になっており(笑)、named pipe なファイルつくってそれを cat しておくと irssi がそこに nicklist を書き込むというような感じになってて、基本的に GNU screen などの縦分割と一緒に使うように設計されている。

で、僕はリモートサーバー上の GNU screen 上で irssi を動かしているので、それをつかうために縦分割をためしてみたわけですが、window 分割したときにでる caption を GNU screen では消すことができず、ローカルで使っている screen の hardstatus の上に、リモート screen の caption が出るという大変いやなかんじになってしまう。

設定見てもどうにも消せないっぽいので、screen 競合として名高い tmux を見てみると普通に消せたのでとりあえずリモートだけ tmux に移行をしてみた。

リモートだけのつもりが tmux をいじっているうちにこれはなかなか良いものだと言うことになり、ローカルも乗り換えるに至った。

まず、tmux をおすすめしてる記事はこれまでもよく目にしてきたがピンとこなかったのは、ほとんどの記事が GNU screen をハードに使ってる人のものではなかったからである。 GNU screen をハードに使ってる人のために僕が tmux の良いところを上げると、

  • tmux 内外問わず、すべての操作をコマンドから行える
  • window 増やさなくても window の中に分割窓(pane)をおける

他にもいろいろあるのだが、この二つは大きい。

tmux 内外問わず、すべての操作をコマンドから行える

これは script 的に動作を拡張しようとしたときに重要になる。 GNU screen でもまぁ screen -X でできるのだが、tmux に比べるとできることが限られており、ちょっと込み入ったことをやろうとするとすぐに screen にパッチを当てる、みたいなことになるw

window 増やさなくても window の中に分割窓(pane)をおける

tmux は window 分割の概念が screen とは異なっている。tmux では分割された小窓は pane とよばれ、window とは定義が違ったものが存在する。それによって window を増やすことなく画面を分割でき、それぞれの window が分割 pane のレイアウトを別々に管理することが可能になっている。

これは好みの問題もあるかもしれないが、僕は tmux 方式が気に入った。

これによって GNU screen 利用時より分割を積極的につかうようになった。特にライフチェンジングだなとおもったのは、分割窓を Emacs でいうところの popwin.el 的に使う方法だ。man をチラ見したり、辞書を引いたりそういうレベルで気軽にpaneをつくれ、man を終了するとpaneが自動で閉じるといった具合に便利に使える。

canything

Emacs 使いが分割窓を popwin 的に使うようになったらまず思いつくのがやっぱり Anything だ。コマンドラインベースのがあったら tmux と相性いいだろうなとおもったらすぐに見つかりました。

canything: CUIでAnything

上記サイトにも乗っているけれど、

$ tmux lsw | canything | cut -d":" -f 1 | xargs tmux select-window -t

とかすれば tmux ウィンドウを anything 風切り替えできるのですが、これを分割窓と組み合わせて、

# .tmux.conf
bind-key b split-window 'tmux lsw | canything | cut -d":" -f 1 | xargs tmux select-window -t'

みたいに設定すると、C-z b (僕はprefixキーz派) で Emacs っぽく画面分割され anything 風しぼりこみインタフェースで window 切り替えできる。すばらしい。

irssi で anything 風チャンネル切り替え

となるとやっぱり真っ先に思いつくのがこれでしょう。まず irssi プラグインを書き、コマンドラインから irssi のチャンネルリストを取得、チャンネル切り替えをできるようにするものを書いた。

channel-socket.pl

これを読み込んで、

/channel-socket start

とすると /tmp/irssi-channels.sock/tmp/irssi-set-channel.sock という二つの UNIX ドメインソケットが作られる。それぞれチャンネル取得用ソケットと、チャンネル切り替え用ソケットだ。

具体的には

$ nc -U /tmp/irssi-channels.sock

でチャンネル一覧取得でき、

$ echo '#emacs-ja' | nc -U /tmp/irssi-set-channel.sock

でチャンネルを切り替えられるっていう具合だ。

これを連結させて

$ nc -U /tmp/irssi-channels.sock | canything | nc -U /tmp/irssi-set-channel.sock

で、anything 風 チャンネル切り替えのできあがり。

これを tmux の分割窓とくみあわせれば完璧。さっきの tmux ウィンドウ切り替えみたいに tmux 側で bind しても良いが、irssi 側でやるのがより自然かなと思う。僕はこんな感じにした。

/bind meta-b command exec - tmux split-window 'nc -U /tmp/irssi-channels.sock | canything -i | nc -U /tmp/irssi-set-channel.sock'

これで irssi 上で M-b すればチャンネル一覧の anything 窓がでる。

Anything like incremental channel switching at irssi

こんな感じ。他にもいろんなことにつかえそうですね!

by typester / at 2012-03-26T06:53:00 / irssi · tmux / Comment

ssh経由でサーバー上のGNU screen上のirssiを一発で開くコマンド

IRCはssh経由でやっていて、毎回sshでつないだあとに手動でscreen attachとかめんどくさいなーと思っていたのですが、

$ ssh example.com -t screen -xR irssi

みたいな感じにすればssh接続と同時にscreen attachするようにできた。便利! (ここでのirssiはコマンド名ではなく、GNU screenのセッション名です。念のため)

irssiっていうalias貼ったらローカルで実行してるような雰囲気になって良い。(実際にはローカルにもirssiいれているのでircというaliasにした)

by typester / at 2012-03-22T14:46:00 / irssi / Comment

Emacsデビューはこの本で決まり! - Emacs実践入門

Emacs界の松岡修造ことtomoyaさんが素敵なEmacs本を書かれたので紹介。

Emacs実践入門 ~思考を直感的にコード化し、開発を加速する (WEB+DB PRESS plus)

Emacsとはなにか? から始まり、インストール、基本的な使い方、カスタマイズ方法といったことが体系的にまとめられたとても良い本。

すでにEmacsユーザーの方は一通り読むことで自分の中で足りない知識を補完することができるし、体系的にまとめられたものを読むことでEmacs脳がかなり整理されるのでぜひ一読することをおすすめする。

そしてEmacsユーザーではないけれど興味があるという人にこそ、この本を薦めたい。そういう人に対してこの本は最適な入門書になっていると思う。 一通り読み終わったあとは自分のマイEmacsを育てる土台ができていることでしょう。

Emacsデビューはこの本で!

by typester / at 2012-03-03T11:10:00 / emacs / Comment

Objective-C スレッドと libuv スレッドとのやりとり

libuv 専用スレッドと通常の Objective-C スレッドとのやりとりの仕方、ついでに書いておく。

tl;dr - libuv スレッドから Objective-C スレッドに対して何か送るときは Objective-C の作法がそのまま使える。逆は uv_async を使う

libuv スレッドから Objective-C スレッド

これは Objective-C の世界の作法がそのまま使える。

iOS4+ と OSX 10.6+ であれば GCD で、

dispatch_async(dispatch_get_main_queue(), ^{
    // ここはメインスレッド
});

のようなのを書くだけでメインスレッドの動作を定義できるから、そこでメソッド呼ぶなり Notification を発行するなりすれば良いので楽ちん。

それ以下の環境だったら performSelector:onThread:withObject:waitUntilDone: 系のを使う。

Objective-C スレッドから libuv スレッド

libuv スレッドでは NSRunLoop が回ってないので上記の作法は使えない。代わりに uv_async を使う。

まず、libuv スレッドで async コールバックを設定:

static void async_cb(uv_async_t* handle, int status) {

}

uv_async_init(self->loop, &self->async, async_cb);

で、呼び出し側(Objective-Cスレッド)から

uv_async_send(&obj->async);

とすれば async_cb が libuv スレッドで発動するという寸法。

データを渡したいときは

@synchronized (obj.send_queue) {
    [obj.send_queue addObject:@"foo"];
}

uv_async_send(&obj->async);

という感じにしておいて、取り出す側も

static void async_cb(uv_async_t* handle, int status) {
    NSArray* queue;

    @synchronized (self.send_queue) {
        queue = [NSArray arrayWithArray:self.send_queue];
        [self.send_queue removeAllObjects];
    }

    // 処理
}

みたいにすれば良い。

async コールバックは複数作ることができるから、用途に応じてコールバックを使い分けるのがよさそう。(データ送信用、スレッド終了用など)

by typester / at 2012-01-24T14:12:00 / objc · libuv / Comment

libuv (libev) と Objective-C autorelease のはまりポイント

iOS や Mac アプリで HTTP 以外のネットワーク機能をつけたいといった場合に、libuv や libev を組み込んで使うというのを割とよくする。方法としては以下のような感じでその機能用のスレッドをつくる:

-(void)run {
    NSThread* thread = [[NSThread alloc] initWithTarget:self
                                               selector:@selector(loop)
                                                 object:nil];
    self.thread = thread;
    [thread release];

    [thread start];
}

スレッドの中身は大体こんな感じ:

-(void)loop {
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];

    uv_loop_t* loop = uv_loop_new();

    // いろいろ初期化
    // ...

    // libuv イベントループ
    uv_run(loop);

    uv_loop_delete(loop);

    [pool drain];
}

このスレッドは uv_run でブロックしてしまう。本来ここではCocoaのイベントループ(NSRunLoop)をまわす部分だが、かわりに libuv のイベントループを回している感じになっている。

したがってこのスレッドで Objective-C を混ぜる場合には autorelease がスレッド終了まで基本的にされなくなるから注意が必要。

これを解決する方法で最初に思いつくのは、uv_run (ev_run) のかわりに uv_run_once (ev_run(..., EVRUN_ONCE)) を使うことだ。

while (1) {
    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    uv_run_once(loop);
    [pool drain];
}

これは一見簡単だけど while ループをとめるフラグを別途用意しないといけないし、uv_run とちがってループを抜けるときには各イベントハンドラが終了しているかを確かめる必要もありめんどくさい。

結果いまはこんな感じにしている:

static void idle_cb(uv_idle_t* handle, int status) {
    uv_idle_stop(handle);
    [(NSAutoreleasePool*)handle->data drain];
    handle->data = NULL;
}

static void check_cb(uv_check_t* handle, int status) {
    uv_idle_t* idle = (uv_idle_t*)handle->data;
    if (NULL != idle->data) return;

    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    idle->data = (void*)pool;
    uv_idle_start(idle, idle_cb);
}

-(void)loop {
    uv_loop_t* loop = uv_loop_new();

    uv_check_t check;
    uv_check_init(loop, &check);
    uv_check_start(&check, check_cb);

    uv_idle_t idle;
    uv_idle_init(loop, &idle);
    check.data = (void*)&idle;
    idle.data = NULL;

    // いろいろ初期化
    // ...

    uv_run(loop);

    uv_loop_delete(loop);
}

uv_check (ev_check) で NSAutoreleasePool をつくりつつ idle タイマーを作って、 その idle タイマー時に [pool drain] する。 これだとイベントが詰まっている場合は drain は呼ばれず、キリの良いときに呼んでくれるから run_once でいちいちやるよりは効率も良さそうな気がする。

このコードでは省略しているけど実際に使うときには checkidle も終了しないと uv_run から抜けてこないのでどこかのオブジェクトにまとめて突っ込んでおいたりして使うのが吉。

こういうのを何も考えずに Objective-C をまぜるともりもりメモリ食うようになるから気をつけよう!

by typester / at 2012-01-24T13:06:00 / objc · libuv / Comment

skype-cli

昨日のコードを元に、skype-cli というコマンドラインツールを書いた。

typester/skype-cli-osx - GitHub

Skype の Desktop API っていうのはマシン上で起動している Skype と通信することで、Skypeの機能にアクセスするAPIで、プラットフォーム毎に通信手段はことなるが、つながってしまったあとの通信内容はテキストベースのプロトコルとなっている。

なので、このテキストプロトコルをtelnet感覚で標準入出力でアクセスできるツールを作ってみたという感じ。

これを子プロセスで実行することで、nodeやEmacsなどからも簡単にSkype APIがたたける、はず。

なんだけど、実際にnodeで以下のようなコードを書いてみてもうまく動かない。

var child_process = require("child_process");

var skype = child_process.spawn("./skype-cli");

skype.stdout.setEncoding("utf8");
skype.stdout.on("data", function (data) {
    console.log("stdout: %s", data);
});

skype.stderr.setEncoding("utf8");
skype.stderr.on("data", function (data) {
    console.log("stderr: %s", data);
});

process.stdin.resume();
process.stdin.setEncoding("utf8");
process.stdin.pipe(skype.stdin, { end: false });

skype.on("exit", function (code) { process.exit(code) });

なーんでか。

by typester / at 2011-12-16T18:00:00 / osx · skype / Comment

Cocoa::Skype とか

Cocoa:: なんちゃらでほしいものを聞いていたときにも挙がっていた Cocoa::Skype だけど、その昔Skype4COMを使った記憶があって、SkypeAPI のバインディング書くのはめんどそうな印象だったのだが、 今日 Skype.framework のヘッダファイルみたら、

#import <Cocoa/Cocoa.h>

@protocol SkypeAPIDelegate;

@interface SkypeAPI : NSObject 
{

}

+ (BOOL)isSkypeRunning;             
+ (BOOL)isSkypeAvailable;       // You can only connect and send commands when this method returns YES.
                                // For example, when Skype is running, but user is logged out, then it returns NO.

+ (void)setSkypeDelegate:(NSObject<SkypeAPIDelegate>*)aDelegate;
+ (NSObject<SkypeAPIDelegate>*)skypeDelegate;
+ (void)removeSkypeDelegate;

+ (void)connect;
+ (void)disconnect;

+ (void)sendSkypeCommand:(NSString*)aCommandString;
@end


// delegate protocol
@protocol SkypeAPIDelegate
- (NSString*)clientApplicationName;
@end

// delegate informal protocol
@interface NSObject (SkypeAPIDelegateInformalProtocol)
- (void)skypeNotificationReceived:(NSString*)aNotificationString;
- (void)skypeAttachResponse:(unsigned)aAttachResponseCode;              // 0 - failed, 1 - success
- (void)skypeBecameAvailable:(NSNotification*)aNotification;
- (void)skypeBecameUnavailable:(NSNotification*)aNotification;
@end

と想像以上に短く、これならすぐバインディング書けそうだなーということで気分転換もかねてPerlバインディングをつくってみた。

typester/Cocoa-Skype - GitHub

使い方は付属の example を参照のこと。 Skype.framework の機能は全部つけてある。 Perl サイドのメソッド名とかはまだ変更するかもしれない。暇なときにドキュメントつけてリリースしよう。

by typester / at 2011-12-15T22:52:00 / perl · skype · osx / Comment

1 2 3 4 5 6 7 8 9 10

(Page 4 of 203)