»
S
I
D
E
B
A
R
«
もっとRubyCocoaでQuicksilverプラグインを書く
February 6th, 2008 by mootoh

RubyCocoaを使ってQuicksilverプラグインを書く の続編です。 前回書いたあと、hisaさんからアドバイスをもらい、RubyCocoaプラグインを書くことができるようになりました。

ポイントは以下の2つ。

  • NSPrincipalClass
  • RubyActionClass < OSX::QSActionProvider

コードは、CodeReposのものをupdateしておきました。 hisaさんコードがたくさん入っていますが、煮るなり焼くなり好きにせよとのことなので、前回と同じ修正BSDライセンスとします。

NSPrincipalClass

Quicksilver プラグインに限らず、Cocoaで何らかのBundleを書く際には、Info.plistの NSPrincipalClass にクラス名を指定しておくと、そのクラスの +load() メソッドが呼ばれてプラグインが組み込まれるようです。 なので、ここでRBBundleInit()を呼んでRubyCocoaを初期化すると。とてもスマート。 前回はこのことを知らずに、無理矢理なハックをしていたのでした。

RCLoader.m:

ここでは、NSPrincipalClassにRCLoaderというクラスを指定しています。

@implementation RCLoader
 
+ (void)load {
  static bool installed = 0;
 
  if (! installed) {
    if (! RBBundleInit("load_ruby.rb", [self class], self)) {
      installed = true;
    }
  }
}

load_ruby.rb:

そんで、RubyCocoaの初期化の中で、必要な.rbを読み込んでおく、と。

def load_ruby_programs(bundle, logger)
  path = bundle.resourcePath.fileSystemRepresentation
  rbfiles = Dir.entries(path).select {|x| /\.rb\z/ =~ x}
  rbfiles -= [ File.basename(__FILE__) ]
  rbfiles.each do |path|
    require( File.basename(path) )
  end
end
 
OSX.init_for_bundle do |bundle, param, logger|
  load_ruby_programs(bundle, logger)
end

RubyActionClass < OSX::QSActionProvider

前回説明したように、QuicksilverのActionを記述するには、QSActionProviderを継承したクラスでメソッドを用意します。 今回は、RubyのクラスでQSActionProviderを実装します。RubyCocoaのパワーがすごすぎる。

class RubyAction < OSX::QSActionProvider
  def act(arg)
    val = arg.stringValue
    OSX::QSObject.objectWithString('Hello world, ' + val)
  end
end

あとは、このRubyActionクラスを、Info.plistのactionClassに、actionSelectoract:に指定しておけば、ちゃんとactが呼ばれます。

疑問

  • OSX.require_framework とか使わないで、QSActionProviderとかのQS frameworkが使えてるのはなぜ?
  • hisaさんは、この方法だとCPU usageが高くなると懸念されているのですが、僕のところではいまひとつ高くなってるように見えません。why?

まとめ

RubyCocoaで、Quicsilverプラグインを書く方法をまとめました。 これで、あとはRubyのクラスとInfo.plistを書くだけでどんどんプラグインが書けますね。みんながんばれ!

あと、自分でもイマイチだなーと思うことでも、何かしら書いて晒すことが大事なんだなと。そんで改善していければOKなんだ。 hisaさん、ありがとうございました。


11 Responses  
hisa writes:
February 6th, 2008 at 5:35 pm

おお、新しくなりましたね。

require_frameworkを明示的に書かなくていいのはすでにQSフレームワークがリンクされているからです。RubyCocoa内部で、QSフレームワークのクラス名が最初に書かれたときにconst_missingでフックされてクラスオブジェクトを探しにいってるはずです。

CPU usageはRubyCocoaのバージョンによったりするのかな?僕は10.5.2に入ってるのをそのまま使ってます。

Objective-Cでbool型を使えるんですね。知らんかった(忘れてた)。どうせなら初期値は0よりfalseの方がいいかも。

mootoh writes:
February 6th, 2008 at 11:25 pm

hisaさん:

フレームワーク

なるほどー。リンクしておけば、探しにいって見つかるのですね。

CPU usage

僕のとこでは、10.5.1 に付属のRubyCocoaです。 Activity Monitor で見ると、たしかにプラグインを有効にしてQuicksilverを起動した場合は、CPU usage が 2-4% になり、無効にしていれば0.5-1% が定常状態となり、CPU時間を食ってますね。プロファイラで調べたら分かるかな。

bool

確かにfalseで初期化すべきですね。やり忘れてました。

kimuraw writes:
February 7th, 2008 at 1:08 am

こまかいですけどObjective-C的には大文字のBOOLでYES/NOです>hisa

ドキュメントされていませんがQuicksilverの機能としては、 Info.plistでQSLoadImmediatelyをtrueにすると NSPrincipalClassで指定したクラスの+(void)loadPlugInが呼ばれる、 というようになっているようです。 Crucible/Code/QSPlugIn.[hm]の_registerPluginのあたり。

mootoh writes:
February 8th, 2008 at 1:16 am

kimurawさん:

たしかに、[currPrincipalClass loadPlugin] してますね。

Quicksilver/Pluginsにあるプラグインで使ってるものは見あたらないみたいですが…どういう意図なんでしょうね。

kimuraw writes:
February 9th, 2008 at 11:00 am

~/Library/Application Support/Quicksilverにある、自分で入れたものでは

  • Clipboard Module
  • Services Menu Module
  • Shelf Module
  • Smoke Actions

が使っているようです。

hisa writes:
February 10th, 2008 at 8:47 am

まだmootohさんのプラグインでは試してなくて、この前メールで送ったプラグインでのことなのですが、プラグインが無効になっている状態のQuicksilverを立ち上げてから有効にすると2-4%くらい(無効だと1%以下)なのですが、プラグインが有効になっている状態のQuicksilverを立ち上げると30-40%くらいから徐々にCPU usageが上がりファンが回り出します。

mootoh writes:
February 12th, 2008 at 12:00 am

hisaさん:

hisaさんに送って頂いたプラグインでためしてみました。 たしかに、こちらを有効にするとCPU usageが50%程度に跳ね上がりますね… Shark.appで簡単にプロファイルとってみました。

http://gyazo.com/60b43424ea23b607f7614c4ca5e004a6.png http://gyazo.com/70e573f2b6c6ef4b7b78a1c56be2a583.png

objc_msgSendがdominantなのかなーと。ものすごい回数のobjc_msgSendが行われているのかと想像しています。

konn writes:
August 25th, 2008 at 11:20 am

初めまして。konnと申します。

これを見て見様見真似で作ってみたのですが、RubyCocoa製のプラグインが複数ある場合、RubyCocoaの初期化を行なう load_ruby.rb の名前をそれぞれ変えないと正しく動作しないようです。

mootoh writes:
August 25th, 2008 at 1:10 pm

konn さん:

参照してくださってありがとうございます。 そうなんですよね、同じ名前で初期化してしまうとハングしてしまいます。

konn writes:
August 25th, 2008 at 9:45 pm

こちらを参考にして作ったプラグインを公開してみました。

http://d.hatena.ne.jp/mr_konn/20080825/1219666577

ありがとうございました。興味がおありでしたらどうぞ。

はてな使ったら負けだと思っている writes:
August 27th, 2008 at 10:06 pm

[RubyCocoa][QSRubyModule][Ruby][プログラミング]Ruby on Quicksilver…

紫ログ:Gauche on Quicksilver – livedoor Blog(ブログ)を見て良いなぁと思ったのでRuby版を作ってみた。 mootoh.log – もっとRubyCocoaでQuicksilverプラグインを書くを見ていつかなにか作りたいなぁと思…

Leave a Reply

»  Substance: WordPress   »  Style: Ahren Ahimsa