マニュアル探査艦

最近ついに講座どころかdiaroidすら更新が停滞し始めましたね・・・f(^^; 久々の U D です。

前チャットに出没したときもほのめかしましたが、いつの間にかなでしこのマニュアル全文検索ツールとして定着しつつあるマニュアル探査艦を、そろそろバージョンアップしたいと思います。次回6月のなでしこバージョンアップまでに対応したいなぁ。(ひとまずマニュアル探査艦Ver.0.81をnako置き場に置いておきます。常に更新中)

検索のロジックやら何やら、全て一から作り直した上で新機能を搭載して、とにかく大幅な全体改善が目標です。Ver.0.81までで実装した主な機能など:

  • サンプル巡察艦のサンプル検索機能をマニュアル探査艦へマージ
  • KonaWiki記法をHTMLに変換するパーサkona2html.nakoの搭載(リファレンスの検索結果を読みやすく!)
  • 検索機能の効率化・高速化(グループを利用した新ロジック)
  • WEB検索機能に「リファレンスググる」を追加(オンラインリファレンスWikiの検索機能)
  • ライブラリの切り分けなど、可能な限りプログラム(プロジェクト)を構造化

だいたいこんなところでしょうか?ほとんどメイン機能は完成しています。あと残っているは今までにあった機能で、まだ実装していないものなどです。TODOメモより未実装機能を抜粋:

  • 複数語検索(AND検索, OR検索) (前の探査艦でも未実装)
  • 検索履歴機能
  • 全角半角・大文字小文字を区別せず検索
  • 設定初期化
  • ツールパネル(起動・編集)

さくっと書いてますが、どれも結構問題がありなかなか一筋縄にはいきません。例えば大文字小文字の区別なんかは、前の探査艦では検索対象・検索語ともに小文字に変換することで検索していましたが、これをすると一気に検索時間が倍以上に膨れ上がります。複数語検索の実装も、DB検索にファイル全文検索、WEB検索と、複数の検索機能を搭載しているためなかなか困難です。

他にも問題はあります。KonaWikiの簡易パーサを組んだのはいいものの、実装中になでしこのバグ(@288)と思しき現象に遭遇しました。どうも「ファイルストリーム一行読む」で空行を読もうとしたときにNULLを4096バイト詰め込んだデータを返してくるようなのです!ちなみに、パーサではこんな感じで一行読むを使っていた:

HANDLEから連続読み込みする ループ
 対象を一行パースして出力

●連続読み込み({整数}Hから|Hで)
 Hのファイルストリーム位置取得
 もしそれが(Hのファイルストリームサイズ)ならば
  不要を戻す
 違えば
  対象=Hでファイルストリーム一行読む
  必要を戻す

もちろんこのままプログラムを走らせたら終了しません。最後の空行でストリーム位置が変なことになってしまうようなので。毎行読んで反復で代替できなくもないのですが、こういうロジックなのでファイルストリーム使った方がさっくり書けるんですよねぇ。

Greasemonkey

最近FirefoxアドオンのGreasemonkeyにはまっています。Greasemonkey、通称「グリモン」は、指定したWebページでユーザスクリプトを実行させることのできるアドオンです。

Greasemonkeyの存在はずっと知っていたのだけれど、使い所が分からず入れてすらいませんでした。しかし最近、大分JavaScriptに慣れてきたので、試しに使ってみるとこれが結構面白い。めちゃくちゃ便利ですね。

……と言っても何のことか分からないかもしれませんね(笑)。例で行きましょう。

例えば、他の人のブログなどを読んでいてJavaScriptなどのソースがpre要素でマークアップされていたとします。このコードを利用したいので、pre要素の内容部分(<pre>〜</pre>)をマウスでコピーしようと、そのエリアを左上から右下までマウスで選択します。ところがこの操作が厄介で、結構、選択したつもりのない部分を選択してしまっていたり、途中で選択が切れていたりします。

で、「クリックしただけでコピーできればいいのにっ」と思ったわけですよ。うん、あるある。

そこでGreasemonkeyの登場。pre要素の部分をクリックしたときに、内容をコピーできるようにしたい。調べてみると(Firefoxの)JavaScriptではクリップボードまで操作できないらしいので、クリック時にtextarea表示に切り替えさせることにする。で、スクリプトを書いたら、Greasemonkeyに登録して、実行させたいページを指定する。すると、ページ閲覧時にスクリプトが自動実行され、ソースコード部分をクリックした時にそういう動作をするように指定ページを拡張できる

で、これがそのJavaScriptコード。コードエリアをクリックすれば自動でtextareaに切り替わる。

// ==UserScript==
// @name           pre2textArea
// @namespace      pre2textArea
// @description    preコードをクリックでtextareaに
// ==/UserScript==

Function.prototype.addEvent = function (oObject, strEvent, bCapture){
	if (oObject.addEventListener) {
		oObject.addEventListener(strEvent, this, bCapture);
	} else if (window.attachEvent) {
		oObject.attachEvent(("on" + strEvent), this);
	}
};

Function.prototype.removeEvent = function (oObject, strEvent, bCapture){
	if (oObject.removeEventListener) {
		oObject.removeEventListener(strEvent, this, false);
	} else if (window.detachEvent) {
		oObject.detachEvent(("on" + strEvent), this);
	}
};

(function (pre2textArea) {
///////////////////////////////////////////////////////////////
// Start: main function ///////////////////////////////////////
(function() {
	var pres, i;
	pres = document.getElementsByTagName('pre');
	for (i=0; i < pres.length; i++) if (pres[i].tagName) {
		pre2textArea(pres[i]).addEvent(pres[i], 'click', false);
	}
}).addEvent(window, 'load', false);
// End: main function /////////////////////////////////////////
///////////////////////////////////////////////////////////////
} )(
	function /* pre2textArea */ (obj) {	
		return function() {
			obj.innerHTML = "<textarea>" + obj.innerHTML + "</textarea>";
			obj.style.padding           = "0px";
			obj.firstChild.style.margin = "0px";
			obj.firstChild.style.padding= "5px";
			obj.firstChild.style.width  = "100%";
			obj.firstChild.style.height = "8em";
			arguments.callee.removeEvent(obj, 'click', false);
		}
	}
);

こんな風に、よく閲覧するページで自分なりの拡張できたりと、とても便利です。調べてみると、他のユーザが作ったGreasemonkey用スクリプトが多数公開されているようです。便利なものがあれば利用していきたい。