Home > Tags > cocoa
cocoa
SafariでMigemoを使えるようにしようとした
- 2008-05-09 (Fri)
- default
SIMBLプラグインをつくる習作として、Safariのページ内検索にMigemoをつかえるようにできないか試行錯誤してみました。 分かったことは、SIMBLプラグインとしてつくるのは難しそう、ということでした。
作戦
Migemoの出力は正規表現です。
例: takai → (タカイ|タカイ|隆一|多階層|他界|高[市石鼾泉井]|たかい|takai|takai)
対して、Safariのページ内検索は1つのキーワードに対する全文検索です。 つまり、探すべきキーワードが1つから複数に変わるということです。これは大きな差。
ならば、元のコードでキーワードを渡して検索している関数を、キーワードの個数ぶんだけ繰り返し呼べば所望の機能が実現できそうだ、と考えました。
どこに手を入れるか
Safariの文字列検索を追う で書いていたように、WebView::searchFor にブレークポイントをはり、デバッガでステップ実行して挙動を調べました。
コードを書き変える
まず、元の searachFor メソッドを _safari_searchFor メソッドに変名してとっておき、 この_safari_searchFor メソッドをMigemoの正規表現から得られる文字列の数だけ呼び出す、という戦略を考えます。 うまくいけば、SIMBLプラグインとして実装する際に Method Swizzling として実現できますね。
ためしに、与えられたキーワードと google の2つで検索するようにしてみました。
Index: mac/WebView/WebViewPrivate.h =================================================================== --- mac/WebView/WebViewPrivate.h (revision 32849) +++ mac/WebView/WebViewPrivate.h (working copy) @@ -106,6 +106,9 @@ */ - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection; +- (BOOL)_safari_searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection; + + - (void)setMainFrameDocumentReady:(BOOL)mainFrameDocumentReady; - (void)setTabKeyCyclesThroughElements:(BOOL)cyclesElements; Index: mac/WebView/WebView.mm =================================================================== --- mac/WebView/WebView.mm (revision 32849) +++ mac/WebView/WebView.mm (working copy) @@ -3002,6 +3002,14 @@ - (BOOL)searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection { + BOOL ret1 = [self _safari_searchFor:@"google" direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:startInSelection]; + BOOL ret2 = [self _safari_searchFor:string direction:forward caseSensitive:caseFlag wrap:wrapFlag startInSelection:startInSelection]; + + return ret1 and ret2; +} + +- (BOOL)_safari_searchFor:(NSString *)string direction:(BOOL)forward caseSensitive:(BOOL)caseFlag wrap:(BOOL)wrapFlag startInSelection:(BOOL)startInSelection +{ if (_private->closed) return NO; @@ -3247,24 +3255,27 @@ - (NSUInteger)markAllMatchesForText:(NSString *)string caseSensitive:(BOOL)caseFlag highlight:(BOOL)highlight limit:(NSUInteger)limit { - WebFrame *frame = [self mainFrame];+ NSString *strs[2] = {@"google", string}; unsigned matchCount = 0; - do { - id <WebDocumentView> view = [[frame frameView] documentView]; - if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) { - [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight]; - ASSERT(limit == 0 || matchCount < limit); - matchCount += [(NSView <WebMultipleTextMatches>*)view markAllMatchesForText:string caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount]; - // Stop looking if we've reached the limit. A limit of 0 means no limit. - if (limit > 0 && matchCount >= limit) - break; - } - - frame = incrementFrame(frame, YES, NO); - } while (frame); - + for (int i(0); i<2; i++) { + WebFrame *frame = [self mainFrame]; + do { + id <WebDocumentView> view = [[frame frameView] documentView]; + if ([view conformsToProtocol:@protocol(WebMultipleTextMatches)]) { + [(NSView <WebMultipleTextMatches>*)view setMarkedTextMatchesAreHighlighted:highlight]; + ASSERT(limit == 0 || matchCount < limit); + matchCount += [(NSView <WebMultipleTextMatches>*)view markAllMatchesForText:strs[i] caseSensitive:caseFlag limit:limit == 0 ? 0 : limit - matchCount]; + + // Stop looking if we've reached the limit. A limit of 0 means no limit. + if (limit > 0 && matchCount >= limit) + break; + } + + frame = incrementFrame(frame, YES, NO); + } while (frame); + } return matchCount; }
じっさいに、マッチしたキーワードをハイライト表示させているのは markAllMatchesForText というメソッドのようだったので、 こちらにも複数キーワード対応するためのハックを仕込んでおきます。
実行結果
複数キーワードがハイライト表示されました。やりましたね :) ただし、「次の候補へ」のようにして、次のマッチ文字列に飛ぼうとしても、同じキーワード間でしかジャンプできませんでした。 ><
原因と対策
そもそも、キーワードにマッチした元のテキストやマッチした結果はどこに保存されているのか。 これを調べていくと WebCore の中に入っていくことになります。 WebCoreはKHTML由来のコードで、C++で書かれているライブラリです。 となると、Objective-C みたいに実行時に柔軟なメソッド差し替えはできなくなってしまいます。 今回はSIMBLプラグインの習作が目的だったので、深追いはここまで。
本気でやるならば、C/Migemoと鬼車をWebCoreにリンクして、マッチしたテキストの範囲などを複数キーワードに対応させればよいでしょう。
まとめ
あと少しだったんだけどなあ…
手駒
- Comments: 2
- Trackbacks: 0
夏ライオンにメッセージフィルタリングをつけるハック
- 2008-05-01 (Thu)
- default
@akrさんがつくっている、夏ライオンというTwitterクライアントに、表示されるメッセージを特定の条件でフィルタリングするハックをしてみました。
何ができるか
特定のユーザのメッセージだけを表示したり、
ある言葉が含まれるメッセージだけを表示したりできます。
キモ
- どこから手をつけるか
- NSPredicate をつかう
長くなるので、続きは以下で。
- Comments: 2
- Trackbacks: 1
CocoaMilk - Lists & Tasks
- 2007-01-21 (Sun)
- default
CocoaMilk : Remember the Milk を Cocoa から の続きをつくっています。
Cocoaのフレームワークに悪戦苦闘しつつ、Remember the MilkのListとTaskを一覧表示できることができるようになりました。
SmartListはどぎつい色でハイライトしたりしています。AddressBook.appのようなインターフェイスが理想です。でもまだそこまでの道のりは長そう…
Cocoaのフレームワークを習得するのはなかなか骨が折れます。まだまだ僕はオブ脳になっていないのでしょう。
翔泳社
売り上げランキング: 103236

OJTのテキストみたいな本です
オブジェクト指向の方法論のみならず実践もまじえてある♪
私にとっては微妙- Comments: 0
- Trackbacks: 0
CocoaMilk : Remember the Milk を Cocoa から
- 2007-01-18 (Thu)
- default
Remember the Milk のデータを、Mac OSXの素晴らしいインターフェイスを使って操作したいと思いました。
ということで、まずCocoaでテーブル表示させるアプリを書いてみました。
REST APIのrtm.lists.getListを使って、Objective-C++で書いています。やっぱり慣れ親しんでいるC++がグッド。
この調子で進めていって、そのうちかっこいいアプリにしたいなというところです。
- Comments: 0
- Trackbacks: 0
Home > Tags > cocoa






