QuickSilver
なんかよくわかんないけど、いつのまにか登録したスクリプトが実行できなくなったりする。あとアイコンがおかしくなったりとか……
QS を再起動すればなおるけどうーん。
なんかよくわかんないけど、いつのまにか登録したスクリプトが実行できなくなったりする。あとアイコンがおかしくなったりとか……
QS を再起動すればなおるけどうーん。
Enter 押すと rename になるのが気になるんだけど挙動変えられないのかなぁ。
GM は .user.js で終わっているからって HTML のページをインストールしようとするなよ><
content-type を読んで欲しい。あと ? 以降は無視してほしい。あとでソース読んでみよう。
http://svn.lab.lowreal.net/lowreal/c/userjs/googlecodesearchautopage.user.js
あとでちゃんと lowreal.net にあげる……
Creammonkey という Safari で userjs を使えるようにするものがあるのですが、userjs を書いている時いちいちメニューから Reload All User Scripts をするのが面倒くさいので改造してみました。
MIT ライセンスらしいのでビルドしたやつを公開。なにぶん Xcode 使ったのも初めてなのでこれでいいのかよくわかりません。ソースを公開したいときとか diff とりたいときってどこまでやればいいのかわからない。
Creammonkey-Debug.zip Original Copyright (c) 2006 KATO Kazuyoshi
Debug というメニュー項目が追加されるので、それをチェックしておけばページリロードのたびに userjs もリロードされます。
ソースを含んでいるのでいぢれる
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 は常用してないのでいいやって感じ。あとで簡単にできそうだったらやってみよう
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 を含んだ文字列でエラー吐くのはなんなんだろう。
$ echo '\\n' |iconv -f utf-8 -t shift-jis iconv: (stdin):1:0: cannot convert
nkf 使いましょう
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 filediff 取りにくいなぁ……このパッチあててもだめかも。手元では動いているけど……
やった変更:
これでメニューの Debug にチェックがついているときのみ毎回リロードするようになる。別の言語ファイルとかよくわからんので放置した。
そういえばメソッドチェインってできないなぁ
http://subtech.g.hatena.ne.jp/cho45/20061030/1162142940
は遅くてアレなので書き直した
http://lab.lowreal.net/trac/browser/c/mac/cpmousecolor.m
CGDisplayAddressForPosition で座標位置の色のアドレスを取得して、unsigned int にキャスト。AARRGGBB になっているので、あとは AA を消して # をくっつける文字列処理
Universal Binary にしようと思ったけど、エンディアンの違いでおかしいのでコードも変えないとだめみたいだ。
CGDisplayBitsPerPixel 使ってちゃんと色数とったほうがいい。32bit 限定
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]+'/';
--- /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 の正式名と同じ感じ。
メニューバーの右のほうのアイコンとかのことをステータスアイテムというらしい。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ちょーかんたん!!
growlremote で飛んで来たやつに URL があったらメニューに追加していくのを作ろうと思ったんだけど、どうも DRb と app.run を組み合わせると BUS Error で落ちる。
delegate 版の growlremote も不定期に落ちるのでどうしよもないなぁ(Growl.rb に依存しているほう使ってる)。うーん

http://lab.lowreal.net/trac/browser/c/mac/openmenu.rb
仕方ないのでプロセス分離した。なのでこれは単にあるディレクトリ以下のファイルを見てメニューを作り、クリックするとそのファイルを開くというだけのもの。
ただし古いファイルは表示せず、無言でファイルを削除する。こわいね!
でもって
./growlserver.rb -c ~/openmenu
で growlremote を起動しておくと webloc を作りまくるのでいい感じ
ポイントは、setMenu で直接メニューを表示させないで、アイテムのクリックを拾ってから popUpStatusItemMenu でメニューを表示させるところかしら。こうするとメニューを表示するまえに処理を挟めるので動的にメニューを表示させられる。AirMac のメニューみたいな。
いつのまにか ssh-agent が複数起動していたりするので、たまに killall ssh-agent やったほうがいいみたいだ。ちょっとすると SSHKeyAgent が終了を検知して起動しなおすか聞いてくるのでそれで起動しなおしてあげる。
cpan にあるのかなぁと思ったけどないっぽいのかなぁ。Python::Serialise::Marshal ならあるけど……
ひさしぶりに gerryyyyyyyyyyyyyyy
#!/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 率がわかって楽しい。
true にしてみた。ちょっとキモいな。すぐ戻すかも
これやめたいんだけど設定が見つからない……
g Cmd+V Enter ってうつとき、Cmd+Enter ってうってしまってキーワード検索できないのがやだ。
$X("//ul[@class='footstamps']/li").forEach(function (i) {
var id = $X("string(./img/@title)", i);
i.appendChild($N("span", {}, id));
});
なんかよくわからん試行錯誤。
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 すると何も書いてない。あやしいなぁ……
めんどいよおお
CPAN は欲しいものがだいたいあるので諦めて、gem をひとつきに一個を目標にして作っていくよ><
名前に迷ったときは CPAN インスパイヤでつけていくことにする。多分一番幸せな方法だ。
gem 化できそうなの
オートリロードでリロードが楽になるのはいいんだけど、リロードさせるために設定をしたりとかするのがすっごいめんどく感じるようになってきたので設定もオートでやろうぜって思った。
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 の宝><
もうちょっといぢってみる。
毎回プロジェクト登録するのめんどいから、なんか包括的なプロジェクトつくって、それにパッケージ追加していくほうがいいのかなぁ。
すごい困る。
gems を使う上で関連づいていなければならない三つ(!)の名前がある
どういう規則でつけるかが決まってない。上のだと 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て書けばいいのか。インデントが増えまくり
あたりが妥当か
しかし
module Foo
end
class Foo #=> Foo is not a class (TypeError)
endとかなるから何をクラスにしてなにをモジュールにするのかが問題に……
って誰かが言ってたネタだったっけ……
サイトにアクセスすると誰かの tty が覗けるサービス。
svk のリポジトリ管理サブコマンドを忘れた。help しても対して情報だしてくれない。
svk help intro
svk mirror --list
UserAgent::RandomProxyByCyberSyndrome
algorithm-diff で常に直近の数行の文字ごとの diff をとりながら、共通する部分をキーワードDBに登録していく。
ログは全てn-gram 式の全文検索エンジンに突っ込んでいく。
直近の diff から得た共通部分からランダムにトピックワードを選択し、全文検索。出てきた結果の上位数件からランダムに行を抽出し、直近の行と再び diff をとる。その結果のキーワードをキーワードDBから取り出した(どうやって?)ランダムなものに置換する。
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") でいけそうだ
解決法:ネットワーク分けない
所属ギルドが解散するらしい。残念だなぁ。
ここ最近ログインしてもコミュニケーションサーバーが重くてギルドチャットがまともに通らないことが多い。直後はしばらく繋がらないから発言できないし。キャラクターチェンジ多いとほぼずっとオフライン扱いになってしまう。直して欲しいな、と書こうと思っていたけどもうどうでもいいな。
大してログインもできないくせにこれから他のギルドに所属するのは面倒くさい。今更知らないギルドに入って相手の考えていることを量りながらチャットするなんてモチベーションは生まれてこないし、そんなに時間がとれない。
そろそろネトゲも卒業ですか。
Provider は RingServer を定期的に再検索するようにしたほうがいいっぽいなぁ。RingServer が落ちてもそれを検知できないから……
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 メソッドをオーバライドしてブロックするようにしてもいいかもしれない。
両方の 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 にしてあげるだけでもいけそうな気がする
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
スクリプトエディタのライブラリ使うとアプリケーションごとのリファレンス見れるのか……
inspect 相当の命令ってないのかなぁ。{1, 1} を "{1, 1}" にするとか
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://lab.lowreal.net/trac/browser/c/lyric/itunes-timetag.rb
/ART-SCHOOL/EVIL/02-WISH.txt みたいな感じになってるのを HTTP からとってきて表示させてみる。
しかし track position が秒単位でしかとれないのでいまいち。
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
endIRC 部分書くのがめんどいので DRb にした。
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 の挙動確認しよう……
インターフェイスビルダー使って実装する方法が未だにわからない。Ruby 側へのコネクションってどうやって張るんだろう。
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みたいしてちょっと読みやすいようにした。
なんかときどき唐突に消えちゃうんだよなぁ。なんでだかわからない。fadein fadeout のコードをコメントアウトしてもなるからそのへんではないし……
数時間かかってわかった…… str.split(//) だけでは文字単位の分割にならないんだ。だから不正な文字がまざって Cocoa 側でエラーになる。
$KCODE を設定するか、正規表現にフラグたてないとだめか。ハマりすぎた。split(//u) にして完了
アイコンは http://www.xfce-look.org/content/show.php?content=23517 が public domain だったので gimpshop で文字のっけて shadow った……gimpshop むずかしすぎる。
drawAtPoint はあんまり連続描画するもんじゃないらしいので LayoutManager を使ってみたい。
ざっと眼を通したけど(メソッド名だけ)めんどくさそう
拡張ライブラリ作ったけど、なんかもっと簡単にやるほうほうがある気がしてならない。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'
とか一応やらないとリンクが通らない
app = NSApplicationWithHotKey.sharedApplication
ref = app.register_hotkey("command+shift+j") do
puts 'hello'
end
app.run学内だとチェックインできねぇ
ってどうやってかくんだ><><
っていうか、学内のネットワークおそぎるんだよおおおおおお
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 読みまくるか
した。 http://lab.lowreal.net/trac/changeset/472
osxhotkey が必要。rubyforge のアカウントが承認されてないので http://lab.lowreal.net/site-ruby/ においとく。
/Developer/Applications/Utilities/Icon Composer.app で作るみたいだ。
Foo.app/Resouces/bar.icns として、Info.plist に
<key>CFBundleIconFile</key>
<string>bar</string>を加えると .app のアイコンになった。
http://lab.lowreal.net/test/IIrcv.dmg
IIrcv.app and dmg にしてみた! バージョン番号さえまだつけてない!
svn の自動で Revision つける keyword を毎回忘れる。
Makefile を Rakefile にしたい。
親モジュールの解析ができてなくて失敗するなぁ。
module = rb_eval_string("OSX");
HotKey = rb_define_class_under(module, "HotKey", rb_cObject);とかやってるせいなんだけど、どうすればいいんだろう。
c_parser のソース読んだけど無理みたいだ。組み込みモジュール以外は認識できないみたい
メニューの意味がわかりにくいよなぁ。隠すと消さないは一個にまとめたい。
みたいな感じなのかな。でも min_alpha 指定してるときは完全に消えるわけじゃないからなぁ
ドキュメント書くのめんどくさい
トイレ詰まった。もっかい流したら流れた。こええ
Windows には Ircv というイカしたメッセージを表示するものがあるのですが、Mac だとこれっぽいのがないので作ってみました。Growl だと時系列が乱れたりするのでなんかだめだってときに便利かもしれません。
これを作るにあたりいろいろ学んだので楽しかった。
あと言語依存を解決したい。Interface Builder で nib 作って読み込む方法がいまだにわからないのでどうにかしたい。
Universal Binary 云々は確認がめんどい割に面白くないのでやる気がおきない。
わかってきた。すっごい便利だなぁ。
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
http://lab.lowreal.net/trac/browser/c/mac/iircv
インターフェイス殆ど書き直した(わらい
しかしまだローカライズファイルを作ってない。もうちょっと使ってみてリリースしよう(リリース?
todo
そういえばこれがわからなかったからキモかったんだよなぁ。調べてたらわかった。Info.plist に指定するらしい。
<key>NSMainNibFile</key>
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>上の例だと Main.nib がロードされる (NSApplicationMain から?)。
NSPrincipalClass はなんか起動時に自動的にインスタンス化されるもの?らしい。ないと console にエラー吐いて起動しない。
newcocoa という gem を作ろうと思った。ので、Makefile 式の Cocoa パッケージングを Rakefile 式に変更中
ソースリポジトリのリビジョン調べる方法がわからない。
svk info するとミラーリポジトリのリビジョンがでてくるし……その先が知りたいのだよ!!(バージョン文字列を自動化したい
PPC では動かないらしい。
エンディアンが関係するようなローレベルなことはやってないんだけどなぁ。hotkey 関連以外でバイナリなのは main.m だけ (Ruby/Cocoa の関数よんでるだけ) だから、たぶん hotkey のライブラリに修正がいるんだと思うけど……
http://lab.lowreal.net/trac/changeset/521
ステルス(マウスが近づいたら消える)を実装しようと思って実装してみた。なんか簡単にできるメソッドが多くてやりやすい。
設定増やさないと
これだと消えてるときに出力されるとフェードインしちゃうな
ちょっとつよいフラグがいりそう
1GB の USB メモリを買った。Windows 版の Ruby と PortableFirefox を入れて持ち歩こうと思う。がっこうの端末はなぜかライブラリがいっさいロードできない。
http://lowreal.net/2006/IIrcv/pkg/ パッケージングした。rake publish するだけだけどな!!
ローカライズを半自動化するようにした。
English.lproj/Main.nib と Japanese.lproj/nib.strings から Japanese.lproj/Main.nib を作るタスクを書いた。
はてなちゃんかわいいよお
そういえば Ruby 以外の LL のスレッド生成方法を全然知らないことに気付いた。JS は timeout/interval で疑似スレッドだしなぁ。
Perl の threads は使おうとするとハマりそう。とにかくスレッド作る時変数がコピーされることと、threads->new (複数形) なことを忘れなければいいのかな。
Ruby のソケットって壮絶に簡単なんだなぁと、他の言語を見てて思う。単に慣れてないだけ、というつっこみっっっっっっg
どうするのがいいんだろう。FoxyProxy が使いにくいし、場所変わるたびに設定するのがめんどくさい。
自動設定ファイルにしても再起動しないと適用されないし、うーん。
あと SSH のトンネリングもちゃんと自動化したいなぁ。ただスリープ入った時に SSH が固まるのがめんどくさい。
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 でいいのだろうか
うーん。いろいろためして 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 ドライブのルートから起動するようにしてるけど、補完とか細かい部分がキモくて……
買った!
Delete の位置が違和感(バッククオートを押してしまう。C-H に矯正すべきか……)
OSX で窓使いの憂鬱みたいなのってないのかな
C 言語を最初に知ったぐらいの時、C 言語は自分にとって楽しい言語じゃなかった。ポインタを理解していなかったし、そもそもコンピュータの仕組みを理解していなかったし、ついでにいえば「下手すればコンピュータが壊れるコードを書く」みたいなことを思っていたので手を出せなかった。
何か知らないうちに Ruby をいぢって、Ruby の拡張ライブラリを読んだり、ちょっと作ってみたりするうちにポインタを理解していることに気付いて、最近 C 言語のキャストについてふとした拍子に理解して、だんだん C がわかるようになってきた。
機械語は読めないものだっていう先入観があったけど、Binary 2.0 あたりの流れでそうじゃないことに気付いた。読む人が読めば読めるもののようだ。なんとなく画像処理について気付いた時と同じ気持ちになった。
頭が悪くても、ゆっくりやっていれば結構どうにかなるのかもしれない。急ぐ事を強要されているけど、無視してもいい気がしてきた。
Ruby はなんとなくで「できそうなもの」だったから、やる気が沸いたんだよなぁ。C はそのとき「できなさそうなもの」だったからやる気が沸かなかった。Perl もそうだ。PHP はまだ「できそうなもの」だった。
どっかとっかかりがあればいいんだよなぁ。電子回路設計とかってどっから入ればいいんだろう。