2006年 11月 01日

QuickSilver

なんかよくわかんないけど、いつのまにか登録したスクリプトが実行できなくなったりする。あとアイコンがおかしくなったりとか……
QS を再起動すればなおるけどうーん。

Finder

Enter 押すと rename になるのが気になるんだけど挙動変えられないのかなぁ。

Greasemonkey

GM は .user.js で終わっているからって HTML のページをインストールしようとするなよ><
content-type を読んで欲しい。あと ? 以降は無視してほしい。あとでソース読んでみよう。

Google Code Search Auto Pager

http://svn.lab.lowreal.net/lowreal/c/userjs/googlecodesearchautopage.user.js
あとでちゃんと lowreal.net にあげる……

2006年 11月 02日

Creammonkey のデバッグ改造版をつくった

[Creammonkey 0.8]( http://blog.8-p.info/articles/2006/12/03/creammonkey-0-8 ) がリリースされたため、そちらをご利用ください :)

Creammonkey という Safari で userjs を使えるようにするものがあるのですが、userjs を書いている時いちいちメニューから Reload All User Scripts をするのが面倒くさいので改造してみました。

MIT ライセンスらしいのでビルドしたやつを公開。なにぶん Xcode 使ったのも初めてなのでこれでいいのかよくわかりません。ソースを公開したいときとか diff とりたいときってどこまでやればいいのかわからない。

Creammonkey-Debug.zip Original Copyright (c) 2006 KATO Kazuyoshi

Debug というメニュー項目が追加されるので、それをチェックしておけばページリロードのたびに userjs もリロードされます。

2006年 11月 01日

Creammonkey をいぢる

ソースを含んでいるのでいぢれる

cd
cd src
cp -r /Volume/Creammonkey/Source Creammonkey
cd ~/Library/InputManagers
ln -s ~/Creammonkey/build/Release/Creammonkey .

で Xcode でプロジェクト開いてビルドすればいいみたい? よくわかんない。

でもってページロード時に毎回ユーザ JS をリロードするパッチ

--- /Volumes/Creammonkey/Source/CMController.m	2006-07-05 23:28:50.000000000 +0900
+++ CMController.m	2006-11-01 16:02:52.000000000 +0900
@@ -234,6 +234,7 @@
     }
 	
     // Eval!
+	[self reloadUserScripts: nil];
 	NSArray* ary = [self matchedScripts: url];
 	int i;
 	for (i = 0; i < [ary count]; i++) {

これだけ。ホントはメニューに Debug とかいうのを作って、それに応じて毎回読むかどうか決める方がいいんだろうけど、Safari は常用してないのでいいやって感じ。あとで簡単にできそうだったらやってみよう

Objective-C

vim の ft は objc

#import <stdio.h>
#import <objc/Object.h>

@interface HelloObj : Object
{
	char* name;
}

- (id) initWithName: (char*)yourname;
- (void) hello: (char*)yourname;
- (void) hello;

@end

//-----

@implementation HelloObj

- (id) initWithName: (char*)yourname {
	// self->name = yourname; // same
	name = yourname;
	return self;
}

- (void) hello: (char*)yourname {
	printf("Hello World! %s\n", yourname);
}

- (void) hello {
	[self hello:name];
}

@end

int main() {
	id obj = [[HelloObj alloc] init];
	// id obj = [HelloObj new];
	[obj hello:"Satoshi"];
	[obj free];

	id obj2 = [[HelloObj alloc] initWithName:"Taro"];
	[obj hello];
	[obj2 free];
	return 0;
}

無駄にクラス使った Hello World!

ところで、iconv が \n を含んだ文字列でエラー吐くのはなんなんだろう。

iconv \n

$ echo '\\n' |iconv -f utf-8 -t shift-jis
iconv: (stdin):1:0: cannot convert

nkf 使いましょう

2006年 11月 02日

Creammonkey Debug mode

diff -ur /Volumes/Creammonkey/Source/CMController.h Creammonkey/CMController.h
--- /Volumes/Creammonkey/Source/CMController.h	2006-03-22 01:07:05.000000000 +0900
+++ Creammonkey/CMController.h	2006-11-02 00:27:29.000000000 +0900
@@ -12,9 +12,12 @@
 	NSMutableArray* scripts_;
 	NSString* scriptDir_;
     NSMutableSet* targetPages_;
+	
+	BOOL isDebug;
 }
 
 - (IBAction) toggleScriptEnable: (id) sender;
+- (IBAction) toggleDebug: (id) sender;
 - (IBAction) uninstallSelected: (id) sender;
 - (IBAction) orderFrontAboutPanel: (id) sender;
 - (IBAction) reloadUserScripts: (id) sender;
diff -ur /Volumes/Creammonkey/Source/CMController.m Creammonkey/CMController.m
--- /Volumes/Creammonkey/Source/CMController.m	2006-07-05 23:28:50.000000000 +0900
+++ Creammonkey/CMController.m	2006-11-02 00:34:43.000000000 +0900
@@ -233,6 +233,9 @@
 		[webView stringByEvaluatingJavaScriptFromString: @"document.body.__creammonkeyed__ = true;"];
     }
 	
+	if (isDebug)
+		[self reloadUserScripts: nil];
+	
     // Eval!
 	NSArray* ary = [self matchedScripts: url];
 	int i;
@@ -248,8 +251,14 @@
     
     [script setEnabled: [sender state] != NSOnState];
     [sender setState: [script isEnabled] ? NSOnState : NSOffState];
-    
-    [self saveScriptsConfig];
+}
+
+- (IBAction) toggleDebug: (id) sender
+{
+	isDebug = !isDebug;
+	[sender setState: isDebug ? NSOnState : NSOffState];
+	
+	[self saveScriptsConfig];
 }
 
 - (IBAction) uninstallSelected: (id) sender
@@ -305,6 +314,8 @@
 	scripts_ = nil;    
     targetPages_ = [[NSMutableSet alloc] init];
 	
+	isDebug = FALSE;
+	
 	[NSBundle loadNibNamed: @"Menu.nib" owner: self];
 	
 	return self;
diff -ur /Volumes/Creammonkey/Source/English.lproj/Menu.nib/classes.nib Creammonkey/English.lproj/Menu.nib/classes.nib
--- /Volumes/Creammonkey/Source/English.lproj/Menu.nib/classes.nib	2006-03-22 01:07:18.000000000 +0900
+++ Creammonkey/English.lproj/Menu.nib/classes.nib	2006-11-02 00:38:41.000000000 +0900
@@ -4,6 +4,7 @@
             ACTIONS = {
                 orderFrontAboutPanel = id; 
                 reloadUserScripts = id; 
+                toggleDebug = id; 
                 toggleScriptEnable = id; 
                 uninstallSelected = id; 
             }; 
@@ -12,7 +13,13 @@
             OUTLETS = {menu = NSMenu; scriptsController = NSArrayController; }; 
             SUPERCLASS = NSObject; 
         }, 
-        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }
+        {CLASS = FirstResponder; LANGUAGE = ObjC; SUPERCLASS = NSObject; }, 
+        {
+            ACTIONS = {toggleDebug = id; }; 
+            CLASS = NSArrayController; 
+            LANGUAGE = ObjC; 
+            SUPERCLASS = NSObjectController; 
+        }
     ); 
     IBVersion = 1; 
 }
¥ No newline at end of file

diff 取りにくいなぁ……このパッチあててもだめかも。手元では動いているけど……

やった変更:

  • Interface Builder で Debug 項目を作成
  • FileOwner の Action に toggleDebug: を追加
  • その二つを connect
  • CMController.{h,m} を編集

これでメニューの Debug にチェックがついているときのみ毎回リロードするようになる。別の言語ファイルとかよくわからんので放置した。

http://lowreal.net/blog/2006/11/02/1

objc メッセージ

そういえばメソッドチェインってできないなぁ

カーソル位置の色取得 2

http://subtech.g.hatena.ne.jp/cho45/20061030/1162142940
は遅くてアレなので書き直した
http://lab.lowreal.net/trac/browser/c/mac/cpmousecolor.m

コンパイル済 (Intel)み
http://svn.lab.lowreal.net/lowreal/c/mac/cpmousecolor

CGDisplayAddressForPosition で座標位置の色のアドレスを取得して、unsigned int にキャスト。AARRGGBB になっているので、あとは AA を消して # をくっつける文字列処理

Universal Binary にしようと思ったけど、エンディアンの違いでおかしいのでコードも変えないとだめみたいだ。

CGDisplayBitsPerPixel 使ってちゃんと色数とったほうがいい。32bit 限定

DAAP via SSH

Leopard では dns-sd コマンドをつかってできます: http://subtech.g.hatena.ne.jp/cho45/20090406/1239021992

http://subtech.g.hatena.ne.jp/cho45/20061027/1161910002
で mDNSProxyResponderPosix がどこにあるのかわからないと書いたけど http://developer.apple.com/networking/bonjour/download/ にあった。

Bonjour Source Code v107.6 をダウンロードして以下のことをした

cd mDNSResponder-107.6/mDNSPosix
make os=tiger
cd build/prod
cp mDNSProxyResponderPosix ~/bin
mDNSProxyResponderPosix 127.0.0.1 squeal "shareName" _daap._tcp. 3689 

はてなサービスを超高速移動するブックマークレット

javascript:location='http://%s.hatena.ne.jp/'+location.pathname.split("/")[1]+'/';
2006年 11月 03日

Creammonkey いぢりで Cocoa Webkit をまなぶ

--- /Volumes/Creammonkey/Source/CMController.m	2006-07-05 23:28:50.000000000 +0900
+++ CMController.m	2006-11-03 02:49:19.000000000 +0900
@@ -8,6 +8,13 @@
 #import "CMUserScript.h"
 
 @implementation CMController
++ (BOOL)isSelectorExcludedFromWebScript:(SEL)aSelector { return NO; }
+- (NSString*) helloHackWebkit:(NSString*) arg
+{
+	return [@"Hello" stringByAppendingString: arg];
+}
+
+
 - (NSArray*) scripts
 {
 	return scripts_;
@@ -233,12 +240,18 @@
 		[webView stringByEvaluatingJavaScriptFromString: @"document.body.__creammonkeyed__ = true;"];
     }
 	
+	if (isDebug) [self reloadUserScripts: nil];
+		
+	WebScriptObject* scriptObject= [webView windowScriptObject];
+	[scriptObject setValue:self forKey:@"__creammonkey_obj"];
+	
     // Eval!
 	NSArray* ary = [self matchedScripts: url];
 	int i;
 	for (i = 0; i < [ary count]; i++) {
         [webView stringByEvaluatingJavaScriptFromString: [ary objectAtIndex: i]];
 	}
+	[scriptObject setValue:nil forKey:@"__creammonkey_obj"];
 }
 
 #pragma mark Action
@@ -252,6 +265,13 @@
     [self saveScriptsConfig];
 }
 
+- (IBAction) toggleDebug: (id) sender
+{
+	isDebug = !isDebug;
+	[sender setState: isDebug ? NSOnState : NSOffState];
+
+}
+
 - (IBAction) uninstallSelected: (id) sender
 {
 	CMUserScript* script = [[scriptsController selectedObjects] objectAtIndex: 0];
@@ -305,6 +325,8 @@
 	scripts_ = nil;    
     targetPages_ = [[NSMutableSet alloc] init];
 	
+	isDebug = FALSE;
+	
 	[NSBundle loadNibNamed: @"Menu.nib" owner: self];
 	
 	return self;

Objctive-C 側のメソッドを JS 側からよんでみる。うえのように書き換えた上で

alert(__creammonkey_obj.helloHackWebkit_("test"));

とかやると Hello test が alert される。

GM_xmlhttprequest を作りたくてどうやるか調べ途中。うえの書き換えだと、eval 後に使ったやつは nil をセットしているけど、これでちゃんと消えてくれるのか (サイト側からそれにアクセスできないのか) が気になる。試せよって感じだけど……

あと上のはファイル分けたりするのがめんどうくさいから self を渡しているけど、専用のクラス/インスタンスを作ってそれを渡すべき。例えば __creammonkey_obj.orderFrontAboutPanel_() とかやると確実に落ちる。

Objctive-C と JS とのデータのやりとりはてきとうにやってくれるっぽい。デフォルトのメソッド名変換は Ruby/Cocoa の正式名と同じ感じ。

2006年 11月 04日

Ruby/Cocoa でステータスアイテムを追加してみる

メニューバーの右のほうのアイコンとかのことをステータスアイテムというらしい。Windows でいうところのタスクトレイ?

require 'osx/cocoa'

include OSX

class Test < NSObject

	def applicationDidFinishLaunching(aNotification)
		menu = NSMenu.alloc.initWithTitle "TEST"
		menu.setDelegate self
		menu.setAutoenablesItems false

		item = menu.addItemWithTitle "TEST", :action, "menuclicked_", :keyEquivalent, ""
		item.setEnabled true

		# new image and resize
		img = NSWorkspace.sharedWorkspace.iconForFileType "unknown"
		size = NSSize.new
		size.width = 16
		size.height = 16
		img.setSize size

		# create status item
		bar = NSStatusBar.systemStatusBar
		item = bar.statusItemWithLength -1
		item.setTitle "Test"
		item.setToolTip "TESTEST"
		item.setImage img
		item.setHighlightMode true
		item.setMenu menu
	end

	def menuclicked(sender)
		p sender
		true
	end
end


app = NSApplication.sharedApplication
app.setDelegate(Test.alloc.init)
p app

trap('SIGINT') { exit }
app.run

ちょーかんたん!!

Ruby/Cocoa menu

growlremote で飛んで来たやつに URL があったらメニューに追加していくのを作ろうと思ったんだけど、どうも DRb と app.run を組み合わせると BUS Error で落ちる。
delegate 版の growlremote も不定期に落ちるのでどうしよもないなぁ(Growl.rb に依存しているほう使ってる)。うーん

openmenu


http://lab.lowreal.net/trac/browser/c/mac/openmenu.rb
仕方ないのでプロセス分離した。なのでこれは単にあるディレクトリ以下のファイルを見てメニューを作り、クリックするとそのファイルを開くというだけのもの。
ただし古いファイルは表示せず、無言でファイルを削除する。こわいね!

でもって

./growlserver.rb -c ~/openmenu

で growlremote を起動しておくと webloc を作りまくるのでいい感じ


ポイントは、setMenu で直接メニューを表示させないで、アイテムのクリックを拾ってから popUpStatusItemMenu でメニューを表示させるところかしら。こうするとメニューを表示するまえに処理を挟めるので動的にメニューを表示させられる。AirMac のメニューみたいな。

2006年 11月 05日

SSHKeyAgent

いつのまにか ssh-agent が複数起動していたりするので、たまに killall ssh-agent やったほうがいいみたいだ。ちょっとすると SSHKeyAgent が終了を検知して起動しなおすか聞いてくるのでそれで起動しなおしてあげる。

Ruby::Marshal->load

cpan にあるのかなぁと思ったけどないっぽいのかなぁ。Python::Serialise::Marshal ならあるけど……

gerry++

ひさしぶりに gerryyyyyyyyyyyyyyy

gerry を visitors で可視化する

#!/usr/bin/ruby

require 'rubygems'
require 'scrapi'
require 'time'

links = Scraper.define do
	process "a[href]", "urls[]"=>"@href"
	result :urls
end.scrape(URI.parse('http://subtech.g.hatena.ne.jp/keyworddiary/gerry'))

links = links.grep(%r[^/.+/¥d{8}$]).map {|link| link.split('/')[1..2]}

links.reverse_each do |username, timestamp|
	next unless username == 'cho45'
	time = Time.parse(timestamp)
	puts %Q|0.0.0.0 - - [#{time.strftime("%d/%b/%Y:00:00:00 +0900")}] "GET /gerry HTTP/1.1" 200 26768 "-" "Gerry"|
end

( http://subtech.g.hatena.ne.jp/secondlife/20061024/1161674443 をほぼ完璧にパクっております)

で、Apache 互換のログファイルをつくって、

gerry_to_apachelog.rb > gerry.log
visitors gerry.log > gerry.html

すれば完成! 曜日ごとの gerry 率がわかって楽しい。

http://lab.lowreal.net/test/gerry.html

2006年 11月 07日

browser.urlbar.autoFill

true にしてみた。ちょっとキモいな。すぐ戻すかも

Cmd+Enter の .com 補完

これやめたいんだけど設定が見つからない……
g Cmd+V Enter ってうつとき、Cmd+Enter ってうってしまってキーワード検索できないのがやだ。

2006年 11月 08日

anond show id

	$X("//ul[@class='footstamps']/li").forEach(function (i) {
		var id = $X("string(./img/@title)", i);
		i.appendChild($N("span", {}, id));
	});

hoe でリリース

なんかよくわからん試行錯誤。
gem install hoe で sow って rake package とかは別にいいとして、rake release がうまくいかないというアレ。rubyforge ライブラリのほうの設定しないとだめっていう話っぽい?

$ rubyforge setup (~/.rubyforge/config.yml が初期化されて開く)

でごたごた書いて group_id, package_id を書いてやると (これ調べるのめんどい) 一応いきそうな幹事にはなる、けど、まだこれだとだめっぽい。なんなんだ

$ rake release VERSION=0.0.5 --trace
-snip-
** Execute release
Logging in
at depth 0 - 18: self signed certificate
Releasing charnames v. 0.0.5 tarball
at depth 0 - 18: self signed certificate
rake aborted!
undefined method `[]' for nil:NilClass
/usr/lib/ruby/gems/1.8/gems/rubyforge-0.3.1/lib/rubyforge.rb:215:in `add_release'
/usr/lib/ruby/gems/1.8/gems/hoe-1.1.2/lib/hoe.rb:246:in `define_tasks'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:387:in `execute'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:387:in `execute'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:357:in `invoke'
/usr/lib/ruby/1.8/thread.rb:135:in `synchronize'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:350:in `invoke'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:1906:in `run'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:1906:in `run'
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/bin/rake:7
/usr/bin/rake:18
exit 1

めんどい。とりあえず手動でリリースしてみた。http://rubyforge.org/frs/?group_id=2552

release_id を html からとってくる処理の部分でこけてる。puts html とかやって見てみるとログインできてないという……
パスワードが単純に間違ってるのかなぁと思って確かめたけど違うようには見えない。cat cookie.dat すると何も書いてない。あやしいなぁ……
めんどいよおお

gem

CPAN は欲しいものがだいたいあるので諦めて、gem をひとつきに一個を目標にして作っていくよ><
名前に迷ったときは CPAN インスパイヤでつけていくことにする。多分一番幸せな方法だ。

gem 化できそうなの

  • safe eval
  • uri からタイトルとかとってくるやつ
  • sakage モールス

オートリロードの設定がめんどいので設定をオートにする試み

オートリロードでリロードが楽になるのはいいんだけど、リロードさせるために設定をしたりとかするのがすっごいめんどく感じるようになってきたので設定もオートでやろうぜって思った。

Rinda::Ring は UDP で検索したり登録したりしてサービス呼び出せるライブラリで、これを使うと一瞬で上のようなことができちゃってオレスゲー感を味わえます。ちょーLL

まず tuplespace を起動する。以下のスクリプトそのまま。このタプルスペースはサービスの情報を統括してる。

require 'rinda/ring'
require 'rinda/tuplespace'

DRb.start_service

ts = Rinda::TupleSpace.new
place = Rinda::RingServer.new(ts)

DRb.thread.join

次に各種リロードサービスを tuplespace に登録するスクリプト。 こいつらはブラウザとともに常駐して、リロード要求をうけつける。これらはもちろん RingServer と同じホストで動いている必要はない。

以下は例

reloadfx.rb

#!/usr/bin/ruby

require 'rinda/ring'
require 'net/telnet'

class Reload
    def reload
        telnet = Net::Telnet.new({
            "Host" => "localhost",
            "Port" => 4242
        })
        telnet.puts("content.location.reload(true)")
        telnet.close
    end
end

reload = Reload.new
DRb.start_service(nil, reload)

provider = Rinda::RingProvider.new(:Reload, DRbObject.new(reload), 'Reload')
provider.provide

DRb.thread.join

reloadsafari.rb

#!/usr/bin/ruby

require 'rinda/ring'
require 'net/telnet'

class Reload
    def reload
        <<-`EOC`
        osascript -e '
        tell application "Safari"
            do JavaScript "location = (location.href);" in document 1
        end tell
        '
        EOC
    end
end

reload = Reload.new
DRb.start_service(nil, reload)

provider = Rinda::RingProvider.new(:Reload, DRbObject.new(reload), 'Reload')
provider.provide

DRb.thread.join

でもって、上記サービスをタプルスペースから検索し、リロードメソッドを呼ぶスクリプト

#!/usr/bin/ruby
# reload.rb
require 'rinda/ring'

DRb.start_service
ts = Rinda::RingFinger.primary

ts.read_all([:name, :Reload, DRbObject, nil]).each do |i|
    begin
        p i[2].reload
    rescue Exception => e
        puts e.message
        puts e.backtrace
    end
end

この reload.rb を呼ぶだけで、何の設定もなしに、ネットワーク内のブラウザをリロードする。

新しくブラウザを起動したら同時にそのブラウザ用の Provider を起動すれば、それも何の設定もなしにリロードしてくれるってわけですよ。やばい!

Rinda::Ring さいこう>< DRb は Ruby の宝><

もうちょっといぢってみる。

rubyforge

毎回プロジェクト登録するのめんどいから、なんか包括的なプロジェクトつくって、それにパッケージ追加していくほうがいいのかなぁ。

パッケージの名前

すごい困る。

gems を使う上で関連づいていなければならない三つ(!)の名前がある

  • require "foo/barbaz" の foo/barbaz
  • Foo::BarBaz.new の Foo::BarBaz
  • gem install foo-barbaz の foo-bar

どういう規則でつけるかが決まってない。上のだと case が保たれてない。

それと CPAN みたいに WebService::Foo::Bar みたいなのを作ろうと思うと、それぞれのライブラリで module WebService を定義してあげないといけない。

begin
  WebService
rescue NameError
  WebService = Module.new
end

begin
  Foo
rescue NameError
  Foo = Module.new
end

とか毎回やるのはアレだしどうするんだろう。

http://wiki.rails2u.com/misc/string_flections
web_service/cgi => WebService::Cgi

module WebService
  module Foo
    class Bar
    end
  end
end

て書けばいいのか。インデントが増えまくり

rule

提供するクラス/モジュール
FooBar::Baz
require の名前
foo_bar/baz
rubyforge プロジェクト名とパッケージ名
foobar-baz

あたりが妥当か

しかし

module Foo
end

class Foo #=> Foo is not a class (TypeError)
end

とかなるから何をクラスにしてなにをモジュールにするのかが問題に……

ttyTube

って誰かが言ってたネタだったっけ……
サイトにアクセスすると誰かの tty が覗けるサービス。

svk

svk のリポジトリ管理サブコマンドを忘れた。help しても対して情報だしてくれない。

svk help intro
svk mirror --list

UserAgent::RandomProxyByCyberSyndrome

2006年 11月 09日

無脳

algorithm-diff で常に直近の数行の文字ごとの diff をとりながら、共通する部分をキーワードDBに登録していく。
ログは全てn-gram 式の全文検索エンジンに突っ込んでいく。

直近の diff から得た共通部分からランダムにトピックワードを選択し、全文検索。出てきた結果の上位数件からランダムに行を抽出し、直近の行と再び diff をとる。その結果のキーワードをキーワードDBから取り出した(どうやって?)ランダムなものに置換する。

Rinda Reload

http://lab.lowreal.net/trac/browser/c/mendoi/autoring

ネットワークまたがった場合のいい方法が浮かばないなぁ。とりあえず chain できるようにしてみた。他に方法あるんだろうか

# 主要 RingServer を uri つきで起動
./ring.rb -u druby://host:4321

でもって違うネットワークでは普通に RingServer をたてて
uri 指定して reload メッセージを別の RingServer の tuplespace に投げるサービスを起動

./ring.rb&
./reload_chain.rb druby://host:4321&

美しくないな。

っていうか上流サーバのあるネットワークで cl.rb 起動されても下流に通知されないからこれじゃだめか。ネットワークが分かれているというより、NAT なのが悪いんだよなぁたぶん。NAT でなければ Finger.new("servername") でいけそうだ
解決法:ネットワーク分けない

mabinogi のギルド

所属ギルドが解散するらしい。残念だなぁ。

ここ最近ログインしてもコミュニケーションサーバーが重くてギルドチャットがまともに通らないことが多い。直後はしばらく繋がらないから発言できないし。キャラクターチェンジ多いとほぼずっとオフライン扱いになってしまう。直して欲しいな、と書こうと思っていたけどもうどうでもいいな。

大してログインもできないくせにこれから他のギルドに所属するのは面倒くさい。今更知らないギルドに入って相手の考えていることを量りながらチャットするなんてモチベーションは生まれてこないし、そんなに時間がとれない。

そろそろネトゲも卒業ですか。

Provider

Provider は RingServer を定期的に再検索するようにしたほうがいいっぽいなぁ。RingServer が落ちてもそれを検知できないから……

RingServer を定期的に再検索する Provider

provider = Rinda::RingProvider.new(:Reload, DRbObject.new(reload), 'Reload')
entry = nil
loop do
	begin
		if entry
			# 登録済みタプルを削除する
			entry.renew(0)
		end
		# RingServer を再検索する
		Rinda::RingFinger.finger.lookup_ring_any
		entry = provider.provide
	rescue DRb::DRbConnError, RuntimeError => e
		# RingServer が見つからないときのエラーをキャッチ
		entry = nil
		puts e.message
	end


	sleep 60
end

なんかいい方法ないかなぁ。これだと Renewer は意味がなくなる。(Renewer はサーバからのリクエストの答えるだけなので、サーバが動いてなければ意味をなさない。)

provide メソッドをオーバライドしてブロックするようにしてもいいかもしれない。

2006年 11月 10日

RingServer を繋ぐ

両方の Server 同士でそれぞれタプルを書き込み合うっていうのがたぶん一番簡単な方法かな?

ts    = Rinda::TupleSpace.new
place = Rinda::RingServer.new(ts)

DRb.start_service(uri, ts)

other_ring_server = DRbObject.new_with_uri("druby://other-network")
ts.notify(tuple_match).each do |t|
  other_ring_server.write(t)
end

でもこれだけだと NAT とかの場合にタプルは取得できるのにサービスに接続できないというハメになりそう。
drb/gw.rb を使わないとだめかな? SimpleDelegator を DRbUndumped にしてあげるだけでもいけそうな気がする

Rinda::PeskyRingProvider

class Rinda::PeskyRingProvider < Rinda::RingProvider
	def provide
		entry = nil
		loop do
			begin
				if entry
					# 登録済みタプルを削除する
					entry.renew(0)
				end
				# RingServer を再検索する
				Rinda::RingFinger.finger.lookup_ring_any
				entry = super
			rescue DRb::DRbConnError, RuntimeError => e
				# RingServer が見つからないときのエラーをキャッチ
				entry = nil
			end

			sleep 60
		end
	end
end

AppleScript

スクリプトエディタのライブラリ使うとアプリケーションごとのリファレンス見れるのか……
inspect 相当の命令ってないのかなぁ。{1, 1} を "{1, 1}" にするとか

rubyosa libxml-ruby

http://rubyosa.rubyforge.org/ を入れようと思ったら libxml-ruby が入らなかった。

extconf.rb:64: undefined method `find_header' for main:Object (NoMethodError)

ruby のバージョンが古いせい (1.8.2) っぽい。
しかし新しいバージョン入れるのめんどい(コンパイルはしてあるけど、置き換えるのがいろいろめんどそう……)ので、

sudo gem install libxml-ruby -- --with-xml2-include=/usr/include/libxml2

した。

rubyosa 使って applescript にインターフェイスにアクセスした場合帰ってくる文字コードは Shift_JIS みたいだ。

タイムタグがついた歌詞ファイルを HTTP でとってきて iTunes に同期させるテスト

http://lab.lowreal.net/trac/browser/c/lyric/itunes-timetag.rb

/ART-SCHOOL/EVIL/02-WISH.txt みたいな感じになってるのを HTTP からとってきて表示させてみる。
しかし track position が秒単位でしかとれないのでいまいち。

今日の gem install

2006年 11月 11日

今日の gem install

  • mechanize

似非 Ircv

Growl の通知は消えてしまうのでうんたらかんたら。Ircv は http://www.misuzilla.org/dist/net/ircv/ です。

http://lab.lowreal.net/trac/browser/c/mac/iicv.rb
Ruby/Cocoa の TransparentHelloWorld を参考にちょっと作り替えただけ。
setNeedsDisplay(true) すると再描画してくれるらしい。
縁取りがどうも簡単にできなくて試行錯誤した。NSStrokeWidthAttributeName を太めにして描画とかやってみたけど、どうもゴミがでて汚い。
しかたないので NSShadow を使ってるけど、薄いので5回重ねてる。おそそ

クリックを透過するのってどうすればいいんだろう……

require 'drb/drb'
require 'time'

o = DRbObject.new_with_uri("druby://localhost:9876")
loop do
	o.call(Time.now.xmlschema)
	sleep 1
end

IRC 部分書くのがめんどいので DRb にした。

2006年 11月 12日

似非 Ircv

IRC を表示する DRb クライアント

require 'drb/drb'
require "rice/irc"
require "rice/observer"

class Ircv < RICE::SimpleClient
	def initialize(uri, nick, user, username, pass, *channels)
		super(nick, user, username, pass, *channels)
		@o = DRbObject.new_with_uri(uri)
	end

	def uped(subject, message)
		super
	end

	def message(subject, message)
		_, nick, user, host = */(.*?)!(.*?)@(.*?)/.match(message.prefix)
		line = '%s %s' % [nick, message.params.join(" ")]
		@o.call(line)
	end

	def downed(subject, message)
		super
	end
end

o = Ircv.new("druby://localhost:9876", "ircv", "ircv", "ircv", "password")
c = RICE::Connection.new('irc-gateway-host', 6667)
c.add_observer(o)

begin
	c.start
rescue RICE::Connection::Closed
	puts 'closed'
	sleep 30
	retry
end

てきとー

折り返し

そういえば折り返しができてないや

実装してみたけど読みにくかった

ステルス

やっぱちゃんと消えるようにしたいなぁ。じゃまだよなぁ。ねむい。

10秒たったらフェイドアウトするようにしてみた。
しかしちゃんと本家 Ircv の挙動確認しよう……

setIgnoresMouseEvents:

nib

インターフェイスビルダー使って実装する方法が未だにわからない。Ruby 側へのコネクションってどうやって張るんだろう。

偽 Ircv

http://lab.lowreal.net/trac/browser/c/mac/iicv.rb
いろいろ変えた。DRb のフロントオブジェクトである proc は write メソッド共通にしたので

class OutIO < IO
	def initialize(write_proc)
		@proc = write_proc
	end

	def write(arg)
		@proc.call(arg)
	end
end

$stdout = OutIO.new(DRb.new_with_uri(uri))

とかもできるはず。あとステータスアイテムを出すようにしたりとか、いろいろ変更した。

DRb クライアント側も

require 'drb/drb'
require "rice/irc"
require "rice/observer"

class Ircv < RICE::SimpleClient
	def initialize(uri, nick, user, username, pass, *channels)
		super(nick, user, username, pass, *channels)
		@o = DRbObject.new_with_uri(uri)
	end

	def uped(subject, message)
		super
	end

	def message(subject, message)
		_, nick, user, host = */(.*?)!(.*?)@(.*?)/.match(message.prefix)
		case message
		when RICE::Command::PRIVMSG
			line = "%s %s %s¥n" % [message.params[0], nick, message.params[1]]
			@o.call(line)
		when RICE::Command::NOTICE
			line = "%s %s %s¥n" % [message.params[0], nick, message.params[1]]
			@o.call(line)
		else
			type = "#{message.class.to_s.sub(/^.*::/o, '').downcase}"
			line = "%s %s %s¥n" % [type, nick, message.params.join(' ')]
			@o.call(line)
		end
	end

	def downed(subject, message)
		super
	end
end

o = Ircv.new("druby://localhost:9876", "ircv", "ircv", "ircv", "password")
c = RICE::Connection.new('host', 6667)
c.add_observer(o)

begin
	c.start
rescue RICE::Connection::Closed
	puts 'closed'
	sleep 30
	retry
end

みたいしてちょっと読みやすいようにした。

iircv

なんかときどき唐突に消えちゃうんだよなぁ。なんでだかわからない。fadein fadeout のコードをコメントアウトしてもなるからそのへんではないし……

数時間かかってわかった…… str.split(//) だけでは文字単位の分割にならないんだ。だから不正な文字がまざって Cocoa 側でエラーになる。
$KCODE を設定するか、正規表現にフラグたてないとだめか。ハマりすぎた。split(//u) にして完了

2006年 11月 13日

iircv だいたいよさげ


アイコンは http://www.xfce-look.org/content/show.php?content=23517 が public domain だったので gimpshop で文字のっけて shadow った……gimpshop むずかしすぎる。

  • width と行数を設定できるように
  • 一番上にゴミが見えることがあるのをちゃんと直す(行数指定とともに)
  • ホットキー(Ruby/Cocoa では無理?)

http://lab.lowreal.net/trac/browser/c/mac/iicv.rb (最新)

wanna

drawAtPoint はあんまり連続描画するもんじゃないらしいので LayoutManager を使ってみたい。
ざっと眼を通したけど(メソッド名だけ)めんどくさそう

RegisterHotKey

拡張ライブラリ作ったけど、なんかもっと簡単にやるほうほうがある気がしてならない。Carbon の関数をインポートする機能ってないんかなぁ

Carbon で拡張ライブラリつくるときのメモ

#include の順番が地味に重要だった。

#include <ruby.h>
#include <Carbon/Carbon.h>

だとコンパイルエラー

#include <Carbon/Carbon.h>
#include <ruby.h>

すればおk

#!/usr/bin/ruby

require 'mkmf'
$CFLAGS << " -framework Carbon "
$LDFLAGS << " -framework Carbon "
create_makefile 'osxhotkey'

とか一応やらないとリンクが通らない

hotkey こんなん

app = NSApplicationWithHotKey.sharedApplication
ref = app.register_hotkey("command+shift+j") do
	puts 'hello'
end

app.run

学内だとチェックインできねぇ

rubygems で拡張ライブラリ

ってどうやってかくんだ><><
っていうか、学内のネットワークおそぎるんだよおおおおおお

拡張ライブラリ

newgem して (Hoe は生成ファイルがよくわからない……) 書いたけど、これでいいのか謎だなぁ。
拡張ライブラリビルドしないと test できないから

Rake::TestTask.new("test") { |t|
	sh %{ruby setup.rb config}
	sh %{ruby setup.rb setup}
	t.libs << "test"
	t.libs << "ext"
	t.pattern = "test/**/*_test.rb"
	t.verbose = true
}

みたいにしたけど、setup.rb に引数わたせないよなぁ。今回は渡す必要ないからいいけどどうするんだろ。
他のライブラリの Rakefile 読みまくるか

iircv ホットキー対応

した。 http://lab.lowreal.net/trac/changeset/472
osxhotkey が必要。rubyforge のアカウントが承認されてないので http://lab.lowreal.net/site-ruby/ においとく。

Mac のアイコン

/Developer/Applications/Utilities/Icon Composer.app で作るみたいだ。
Foo.app/Resouces/bar.icns として、Info.plist に

	<key>CFBundleIconFile</key>
	<string>bar</string>

を加えると .app のアイコンになった。

2006年 11月 14日

IIrcv.dmg

http://lab.lowreal.net/test/IIrcv.dmg
IIrcv.app and dmg にしてみた! バージョン番号さえまだつけてない!
svn の自動で Revision つける keyword を毎回忘れる。

Makefile を Rakefile にしたい。

C の rdoc

親モジュールの解析ができてなくて失敗するなぁ。

	module = rb_eval_string("OSX");
	HotKey = rb_define_class_under(module, "HotKey", rb_cObject);

とかやってるせいなんだけど、どうすればいいんだろう。

c_parser のソース読んだけど無理みたいだ。組み込みモジュール以外は認識できないみたい

IIrcv キーワードハイライトを実装

IIrcv

メニューの意味がわかりにくいよなぁ。隠すと消さないは一個にまとめたい。

  • 表示されてないとき -> 表示して隠さないようにする
  • 表示されているとき -> 隠す

みたいな感じなのかな。でも min_alpha 指定してるときは完全に消えるわけじゃないからなぁ

2006年 11月 15日

ドキュメント書くのめんどくさい

todo

  • universal binary (拡張ライブラリのコンパイル/検証するのがめんどい)

gerry++

トイレ詰まった。もっかい流したら流れた。こええ

2006年 11月 16日

IIrcv - dRuby インターフェイスの時系列通知サーバ

IIrcv - 汎用通知サーバ with dRuby

Windows には Ircv というイカしたメッセージを表示するものがあるのですが、Mac だとこれっぽいのがないので作ってみました。Growl だと時系列が乱れたりするのでなんかだめだってときに便利かもしれません。

これを作るにあたりいろいろ学んだので楽しかった。

  • Cocoa 全般の構造
  • アプリケーションバンドルの作り方
  • バンドル内のファイルのアクセス法
  • NSLayoutManager の使い方少し
  • .icns ファイルの作り方 (/Developer/Applications/Utilities/Icon Composer.app)
  • dmg ファイルをコマンドラインから作る方法 (hdiutil create)
  • 拡張ライブラリの実装法とドキュメントの書き方
  • 拡張ライブラリ rubygems の作り方
  • ユーザ入力が必要な実装のテストの書き方

あと言語依存を解決したい。Interface Builder で nib 作って読み込む方法がいまだにわからないのでどうにかしたい。

Universal Binary 云々は確認がめんどい割に面白くないのでやる気がおきない。

catalyst


フォント等幅で ./script/testforiircv_server.pl -d 2>&1 | iircvstdout.rb

InterfaceBuilder

わかってきた。すっごい便利だなぁ。

  • アウトレットって何? => インスタンス変数の変な名称
  • アクションって何? => インスタンスメソッドの変な名称

Ruby のクラスを作りたい場合を(とは限らないけど)、例えば Classes で NSObject を選んで Classes -> Subclass ... するとサブクラスができるので、それに対してアウトレット/アクションを設定する。でもって Instantiate ... するとインスタンスが出現するので、Ctrl + ドラッグで配置したコントロールとアウトレット/アクションを結びつけていく。
例えばボタンを Ctrl クリックしてそのインスタンスされたオブジェクトにドロップするとアクション一覧がでてどれに接続するか選べる。
とかいうものらしい。あとは Ruby 側でインスタンス化したりするのと一緒だけど、アプリケーションバンドル化しないとうまく実行できないのでちょっとめんどい。Makefile 書いて、make clean; make; open IIrcv.app みたいなのを毎回実行するようにしてる。

おまけ。Create Files For ... するとクラスのひな形を作ってくれていいんだけど、もちろん Objective-C。なので Ruby に変換するのを Ruby ででっちあげた。

#!/usr/bin/ruby

require 'erb'

header = ARGF.read
_, class_name, super_class = */@interface ([^¥s]+) : ([^¥s]+)/.match(header)

outlets = header.scan(/IBOutlet id (.*?);/)
actions = header.scan(/^- ¥(IBAction¥)(.*?):¥(id¥)sender;/)

ERB.new(DATA.read, $SAFE, '-').run
__END__
require 'osx/cocoa'
include OSX

class <%=class_name%> < <%=super_class%>
	<%- outlets.each do |outlet| -%>
	ib_outlets :<%=outlet%>
	<%- end %>
	<%- actions.each do |action| -%>

	def <%=action%>(sender)
	end
	<%- end %>

	def awakeFromNib
	end
end
2006年 11月 17日

nib! nib!

http://lab.lowreal.net/trac/browser/c/mac/iircv
インターフェイス殆ど書き直した(わらい

  • 設定ウィンドウを追加。
  • メニューも nib から読むように

しかしまだローカライズファイルを作ってない。もうちょっと使ってみてリリースしよう(リリース?

todo

  • ローカライズ
  • ホットキーの設定がない (Set Key! とかでるやつってどうやって実装すればいいんだ)
  • Universal Binary

nib のファイル名はどこで指定するのか

そういえばこれがわからなかったからキモかったんだよなぁ。調べてたらわかった。Info.plist に指定するらしい。

	<key>NSMainNibFile</key>
	<string>Main</string>
	<key>NSPrincipalClass</key>
	<string>NSApplication</string>

上の例だと Main.nib がロードされる (NSApplicationMain から?)。
NSPrincipalClass はなんか起動時に自動的にインスタンス化されるもの?らしい。ないと console にエラー吐いて起動しない。

2006年 11月 18日

次の gem

newcocoa という gem を作ろうと思った。ので、Makefile 式の Cocoa パッケージングを Rakefile 式に変更中

2006年 11月 19日

svk

ソースリポジトリのリビジョン調べる方法がわからない。
svk info するとミラーリポジトリのリビジョンがでてくるし……その先が知りたいのだよ!!(バージョン文字列を自動化したい

2006年 11月 20日

IIrcv rev513 universal binary

PPC では動かないらしい。
エンディアンが関係するようなローレベルなことはやってないんだけどなぁ。hotkey 関連以外でバイナリなのは main.m だけ (Ruby/Cocoa の関数よんでるだけ) だから、たぶん hotkey のライブラリに修正がいるんだと思うけど……

IIrcv changeset 521

http://lab.lowreal.net/trac/changeset/521
ステルス(マウスが近づいたら消える)を実装しようと思って実装してみた。なんか簡単にできるメソッドが多くてやりやすい。

設定増やさないと

これだと消えてるときに出力されるとフェードインしちゃうな
ちょっとつよいフラグがいりそう

http://lab.lowreal.net/trac/changeset/522

USB memory

1GB の USB メモリを買った。Windows 版の Ruby と PortableFirefox を入れて持ち歩こうと思う。がっこうの端末はなぜかライブラリがいっさいロードできない。

gerry++

rev525

http://lowreal.net/2006/IIrcv/pkg/ パッケージングした。rake publish するだけだけどな!!
ローカライズを半自動化するようにした。
English.lproj/Main.nib と Japanese.lproj/nib.strings から Japanese.lproj/Main.nib を作るタスクを書いた。

2006年 11月 21日

あああ

はてなちゃんかわいいよお

2006年 11月 22日

Thread

そういえば Ruby 以外の LL のスレッド生成方法を全然知らないことに気付いた。JS は timeout/interval で疑似スレッドだしなぁ。
Perl の threads は使おうとするとハマりそう。とにかくスレッド作る時変数がコピーされることと、threads->new (複数形) なことを忘れなければいいのかな。

Socket

Ruby のソケットって壮絶に簡単なんだなぁと、他の言語を見てて思う。単に慣れてないだけ、というつっこみっっっっっっg

Fx のプロキシ設定を自動化

どうするのがいいんだろう。FoxyProxy が使いにくいし、場所変わるたびに設定するのがめんどくさい。
自動設定ファイルにしても再起動しないと適用されないし、うーん。
あと SSH のトンネリングもちゃんと自動化したいなぁ。ただスリープ入った時に SSH が固まるのがめんどくさい。

Hash merge

require 'pp'

class Hash
	def deep_merge(other)
		deep_proc = Proc.new { |k, s, o|
			if s.kind_of?(Hash) && o.kind_of?(Hash)
				next s.merge(o, &deep_proc)
			end
			next o
		}
		merge(other, &deep_proc)
	end
end

a = {
	:hoge => 'hoge',
	:fuga => {
		:aaaa => 'aaaa',
		:bbbb => 'bbbb',
		:dddd => {
			:test => 'test',
		}
	},
}

b = {
	:hoge => 'hoge',
	:hage => 'ore',
	:fuga => {
		:bbbb => 'baka',
		:cccc => 'remon',
		:dddd => {
			:TTst => 'test',
		}
	},
}

pp a.merge(b)
pp a.deep_merge(b)
:!/usr/bin/ruby tmp/test.rb                                                                                                                                                   
{:hoge=>"hoge",
 :hage=>"ore",
 :fuga=>{:bbbb=>"baka", :dddd=>{:TTst=>"test"}, :cccc=>"remon"}}
{:hoge=>"hoge",
 :hage=>"ore",
 :fuga=>
  {:aaaa=>"aaaa",
   :bbbb=>"baka",
   :dddd=>{:TTst=>"test", :test=>"test"},
   :cccc=>"remon"}}

みたいなのって AS にもあったりするのかな

わー

Perl のテストの書き方わかんねー(基本がそもそも

perl -Ilib t/*.t でいいのだろうか

2006年 11月 24日

cygwin

うーん。いろいろためして DOS プロンプトで生きていこうと思ったけど難しいなぁ。
USB メモリに cygwin インストールしたほうがいいのかもしれない。

@echo off
PATH ¥bin;¥ruby¥bin;¥putty;¥vim7;%PATH%

title  Console
prompt $_$P$_$G 
doskey ls=dir /B $*
doskey lm=dir /OD $*
doskey cat=type $*
doskey less=more $*
doskey diff=fc $*
doskey rm=del $*
doskey rm-rf=rmdir /s /q $*
doskey findstr=grep $*
doskey mv=move $*
doskey cp=copy $*
doskey cp-r=xcopy $*
doskey clear=cls
doskey ps=tasklist $*
doskey ..=cd ..
doskey kill=taskkill /PID $*
doskey traceroute=tracert $*
doskey vim=start ckw.exe -e vim7.exe $*

cmd

みたいなのを USB ドライブのルートから起動するようにしてるけど、補完とか細かい部分がキモくて……

2006年 11月 28日

HHKB Pro2

買った!
Delete の位置が違和感(バッククオートを押してしまう。C-H に矯正すべきか……)

mayu

OSX で窓使いの憂鬱みたいなのってないのかな

2006年 11月 29日

C language って検索しにくいんだよ!!

C 言語を最初に知ったぐらいの時、C 言語は自分にとって楽しい言語じゃなかった。ポインタを理解していなかったし、そもそもコンピュータの仕組みを理解していなかったし、ついでにいえば「下手すればコンピュータが壊れるコードを書く」みたいなことを思っていたので手を出せなかった。

何か知らないうちに Ruby をいぢって、Ruby の拡張ライブラリを読んだり、ちょっと作ってみたりするうちにポインタを理解していることに気付いて、最近 C 言語のキャストについてふとした拍子に理解して、だんだん C がわかるようになってきた。

機械語は読めないものだっていう先入観があったけど、Binary 2.0 あたりの流れでそうじゃないことに気付いた。読む人が読めば読めるもののようだ。なんとなく画像処理について気付いた時と同じ気持ちになった。

頭が悪くても、ゆっくりやっていれば結構どうにかなるのかもしれない。急ぐ事を強要されているけど、無視してもいい気がしてきた。

Ruby はなんとなくで「できそうなもの」だったから、やる気が沸いたんだよなぁ。C はそのとき「できなさそうなもの」だったからやる気が沸かなかった。Perl もそうだ。PHP はまだ「できそうなもの」だった。

どっかとっかかりがあればいいんだよなぁ。電子回路設計とかってどっから入ればいいんだろう。