最速検索の勉強 - CPAN最速検索

こんにちは、最速検索co(さいそくけんさくこ)です。嘘ですごめんなさい。

今回はCPAN最速検索を読んでみよう、という無謀な試み。

全モジュールのリストを改行で区切ったテキストファイルを受信してクライアントサイドで検索させています。クライアントサイドで検索させているのでサーバー負荷は全くかかりません。

えー、前回ソースをだらだらと載せてしまったのですが今回は関数名とポイントだけに絞ります。必要なら各自ソースを並べて読んでください。

bodyタグ

  • bodyタグの中はmainとmenuのdivタグ、menuの中はdistとdocのdivタグという構造。distに何が表示されるかわかりませんがとりあえず読み進めます。
  • あ、menuの下にresultのdivタグがありました。ここはインクリメンタル検索結果っぽい。inputタグでonkeydown="keydown.call(this,event)"となっていますので、keydown関数で更新ですね。
  • ie_xmlhttp.jsを読み込んでいますが後回し。

gid()

  • gid()の気持ちはよくわかります。うわ、$に代入して$(id)とかできるんですね。
  • 初期化関数はinitと。

function addSidebar(title, url)

  • 省略

function loadperldoc(pn)

  • pnは選択中のパッケージ名が入るようです。
  • あ、perldocの内容は都度サーバに問い合わせるんですね。

function pn2dist(pn)

  • // パッケージネームからdistを探す
  • A::B::C → A::B → A のように探しているようです。複数のパッケージをまとめて「配布」しているのがdistということのようです。あ、そういえばPerlのモジュールはpackage 〜;とか書きましたね。

function searchdist(pn)

  • setTimeout(f,600)しています。600msecですよね。0.6秒後にfを呼んでいる。多分keydownあたりから呼ばれていると想像。
  • f()ではdistのinnerHTMLを更新しています。ああ、配布名とパッケージ名のリンクを作っていました。リンク先は両方ともloadperldoc(this.innerHTML)。

function init()

  • 初期化関数ですね。ajax()を2回呼んでいます。それぞれコールバックを登録しているようですが、いったん後回しにします。
function init(){
  ajax("./list", function(data){
    find = new Finder({
      src    : data,
      formatter : formatter,
      view   : printto("result"),
      onchange : searchdist
    });
    watch("query", find.do_search);
    $("query").focus();
  });
  ajax("./dist", function(data){
    dist = data;
  });
}

function formatter(text,sel)

  • textをspanで囲ってonclick="loadperldoc(this.innerHTML)属性をつけます。
  • さらにselが真ならclass="selected"属性もつけます。

function printto(id)

  • id要素に値を設定する関数を返します。

function keydown(event)

  • 「上下で選択、エンターでperldoc表示」のようです。

function watch(id, callback, msec)

  • id要素が変更されたかどうかをmsec(省略すると200)間隔で確認し、変更されていたらcallbackを呼び出します。

function Finder(option)

  • お、1画面で収まらない。いったん読み飛ばします。

Array.prototype.map = function(callback,thisObj)

  • RubyでいうArray#mapのようです。

String.prototype.find = function(q,op)

  • RubyでいうString#matchのようです。
  • opはop.max||10という使われ方で件数を絞るのに使っているようです。

function ajax(url,callback)

function ajax(url,callback){
  $("status").innerHTML = "now loading...";
  var req = new XMLHttpRequest;
  req.open("GET",url,true);
  req.onload = function(){
    var data = req.responseText;
    callback(data);
    $("status").innerHTML = "loaded."; 
  };
  req.send(null)
}
  • ははあ、第1引数はURLでしたか。本当にコールバックを登録してGETするだけのようです。

function init() [再掲]

function init(){
  ajax("./list", function(data){
    find = new Finder({
      src    : data,
      formatter : formatter,
      view   : printto("result"),
      onchange : searchdist
    });
    watch("query", find.do_search);
    $("query").focus();
  });
  ajax("./dist", function(data){
    dist = data;
  });
}
  • ajax()の定義を見つつ読み下してみます。
  • おお。http://cpan.ma.la/listhttp://cpan.ma.la/distに検索結果を先に入れてある。
  • ./listの方は、入力エリアを0.2秒間隔で監視して変更があればFinder()にパラメータを渡して作った関数で再検索。ははあ、onkeydownでは再検索しないと。
  • ./distの方は、バックグラウンドで内容を変数distに取り込んでいました。