Hatena::Groupkeysnail

basyura snail

 | 

2010-03-28

Ruby API 検索 その3 - メソッドも補完

| 22:07 |  Ruby API 検索 その3 - メソッドも補完 - basyura snail を含むブックマーク はてなブックマーク -  Ruby API 検索 その3 - メソッドも補完 - basyura snail

最初はクラス名を補完。# を入力した後はそのクラスのインスタンスメソッドを補完。

補完用ファイルをゴリッと作ったらサイズがでかくなったので、テキストファイルサーバに置いておいて XMLHttpRequest で取得するように修正。

微妙にファイルサイズがでかいので、キャッシュして持っておくのもなんだなぁと思うので、ウイークリファレンス的なことをしたいんだけど無理?。リファレンスページを開いた時点で変数(ruby_completes)に null を突っ込んでもいいけど、このメモリってちゃんと回収されるんだろうか?定義ファイルを読み込み直した時点で null で初期化されるけど。

サーバRuby で補完候補を都度作って通信してもいいけど、Ruby のバージョン分沢山用意するのもめんどい。速度はそんなに遅くないと思うけど試してない。

リファレンスページのヒット率が高いのか低いのかが謎 (><)

let ruby_completes = null;
shell.add("refe" , M({ja: "Ruby リファレンス検索", en: "ruby reference search"}) ,
  function (args, extra) {
    function generate_url(word) {
      let site   = "http://doc.okkez.net/188";
      let clazz  = word.split("#")[0];
      let method = word.split("#")[1];
      //let clazz  = word.split("\.")[0];
      //let method = word.split("\.")[1];
      // not match. search by google with site: .
      if(ruby_completes["classes"].indexOf(clazz) == -1) {
        let w = encodeURIComponent(word + " site:" + site);
        return "http://www.google.co.jp/search?q=" + w + "&ie=utf-8&oe=utf-8";
      }
      // no method. open clazz's
      if(method == undefined) {
        return site + "/view/class/" + clazz;
      }
      // try to find clazz's method
      let url = site + "/view/method/" + clazz + "/i/" + encode_method(method);
      if(isAvailable(url)) {
        return url;
      }
      // try to find object's method
      url = site + "/view/method/Object/i/" + encode_method(method);
      if(isAvailable(url)) {
        return url;
      }
      /*
      // try to find singleton's method
      url = site + "/view/method/" + clazz + "/s/" + encode_method(method);
      if(isAvailable(url)) {
        return url;
      }
      // try to find module's method
      url = site + "/view/method/" + clazz + "/m/" + encode_method(method);
      if(isAvailable(url)) {
        return url;
      }
      // try to find special method
      url = site + "/view/method/" + clazz + "/v/" + encode_method(method);
      if(isAvailable(url)) {
        return url;
      }
      // try to find const
      url = site + "/view/method/" + clazz + "/c/" + encode_method(method);
      if(isAvailable(url)) {
        return url;
      }
      */
      // open clazz's 
      return site + "/view/class/" + clazz;
    }
    function isAvailable(url) {
      var http = new XMLHttpRequest();
      http.open("HEAD" , url , false);
      http.setRequestHeader("accept-language" , "ja");
      http.setRequestHeader("Cache-Control"   , "no-cache");
      http.setRequestHeader("content-type"    , "application/x-www-form-urlencoded");
      http.send();
      return http.status == 200;
    }
    function encode_method(method) {
      return encodeURIComponent(method).replace("%","=");
    }
    // open tab
    let url = generate_url(extra.left)
    gBrowser.loadOneTab(url, null, null, null, extra.bang);
  },
  {
    bang      : true,
    literal   : 0,
    completer : function (args, extra) {
    function get_completes() {
      var http = new XMLHttpRequest();
      http.open("GET" , "http://basyura.org/ruby_completes/1.8.8.txt" , false);
      http.setRequestHeader("accept-language" , "ja");
      http.setRequestHeader("Cache-Control"   , "no-cache");
      http.setRequestHeader("content-type"    , "application/x-www-form-urlencoded");
      http.send();
      return http.responseText;
    }
    if (ruby_completes == null) {
      ruby_completes = eval("(" + get_completes() + ")");
    }
    if(extra.left.indexOf("#") != -1) {
      let clazz = extra.left.split("#")[0];
      let list  = ruby_completes[clazz];
      if(list != undefined) {
            return completer.matcher.substring(list)(extra.left || "");
      }
    }
      return completer.matcher.substring(ruby_completes["classes"])(extra.left || "");
    }
  },
  true
);

補完用ファイルはこんな感じ。

{
"classes":["Array" , "String" , ...],
"Array":["Array#find" , "Array#inspect" , ...],
"String":["String#upcase!" , "String#zip" , ...], 
・・・
}
トラックバック - http://keysnail.g.hatena.ne.jp/basyura/20100328
 |