]> gitweb @ CieloNegro.org - sugar.git/blobdiff - dot-files/_vimperator/plugin/multi_requester_js
Auto commit by The Sugar System.
[sugar.git] / dot-files / _vimperator / plugin / multi_requester_js
diff --git a/dot-files/_vimperator/plugin/multi_requester_js b/dot-files/_vimperator/plugin/multi_requester_js
new file mode 100644 (file)
index 0000000..90ca321
--- /dev/null
@@ -0,0 +1,493 @@
+/*** BEGIN LICENSE BLOCK {{{
+  Copyright (c) 2008 suVene<suvene@zeromemory.info>
+
+  distributable under the terms of an MIT-style license.
+  http://www.opensource.jp/licenses/mit-license.html
+}}}  END LICENSE BLOCK ***/
+// PLUGIN_INFO//{{{
+var INFO = xml`
+<plugin name="multi_requester" version="0.4.16"
+        href="https://github.com/vimpr/vimperator-plugins/raw/master/multi_requester.js"
+        summary="request, and the result is displayed to the buffer."
+        xmlns="http://vimperator.org/namespaces/liberator">
+    <author href="http://zeromemory.sblo.jp/">suVene</author>
+    <license>MIT</license>
+    <project name="Vimperator" minVersion="3.6"/>
+    <p>
+      <code><![CDATA[
+== Needs Library ==
+- _libly.js(ver.0.1.19)
+  @see http://coderepos.org/share/browser/lang/javascript/vimperator-plugins/trunk/_libly.js
+
+== Usage ==
+>||
+command[!] subcommand [ANY_TEXT]
+||<
+- !        create new tab.
+- ANY_TEXT     your input text
+
+e.g.)
+>||
+:mr  alc[,goo,any1,any2…] ANY_TEXT       -> request by the input text, and display to the buffer.
+:mr! goo[,any1,any2,…]  {window.selection} -> request by the selected text, and display to the new tab.
+||<
+
+== Custumize .vimperatorrc ==
+=== Command(default [ mr ]) ===
+>||
+let g:multi_requester_command = "ANY1, ANY2, ……"
+or
+liberator.globalVariables.multi_requester_command = [ ANY1, ANY2, …… ];
+||<
+
+=== Default Sites (default undefined) ===
+>||
+liberator.globalVariables.multi_requester_default_sites = "alc,goo"
+||<
+These sites(subcommands) will be used, if this variable has been defined and you do not specify subcommands.
+
+=== SITEINFO ===
+e.g.)
+>||
+javascript <<EOM
+liberator.globalVariables.multi_requester_siteinfo = [
+  {
+    map:            ",me",              // optional: keymap for this siteinfo call
+    bang:           true,               // optional:
+    args:           "any"               // optional:
+    name:           "ex",               // required: subcommand name
+    description:    "example",          // required: commandline short help
+    url:            "http://example.com/?%s",     // required: %s <-- replace string
+    xpath:          "//*",              // optional: default all
+    srcEncode:      "SHIFT_JIS",        // optional: default UTF-8
+    urlEncode:      "SHIFT_JIS",        // optional: default srcEncode
+    ignoreTags:     "img",              // optional: default script, syntax "tag1,tag2,……"
+    extractLink:    "//xpath"           // optional: extract permalink
+  },
+];
+EOM
+||<
+
+=== other siteinfo by wedata. ===
+  @see http://wedata.net/databases/Multi%20Requester/items
+
+=== Mappings ===
+e.g.)
+>||
+javascript <<EOM
+liberator.globalVariables.multi_requester_mappings = [
+  [ ",ml", "ex" ],              // == :mr  ex
+  [ ",mg", "goo", "!" ],        // == :mr! goo
+  [ ",ma", "alc",  , "args" ],  // == :mr  alc args
+];
+EOM
+||<
+
+=== Other Options ===
+>||
+let g:multi_requester_use_wedata = "false"       // true by default
+||<
+wedata を利用しない場合は false を設定してください。
+>||
+let g:multi_requester_default_sites = 'alc';
+||<
+subcommand を省略した場合に利用されるサイトを設定します。
+>||
+let g:multi_requester_order = 'count'; // date by default
+||<
+補完の順番を設定します。(大きい順に並びます)
+"count" または "date" を設定してください。
+      ]]></code>
+    </p>
+</plugin>`;
+//}}}
+(function() {
+if (!liberator.plugins.libly) {
+  liberator.log("multi_requester: needs _libly.js");
+  return;
+}
+
+// global variables {{{
+var DEFAULT_COMMAND = [ "mr" ];
+var SITEINFO = [
+  {
+    name: "alc",
+    description: "SPACE ALC (\u82F1\u8F9E\u6717 on the Web)",
+    url: "http://eow.alc.co.jp/%s/UTF-8/",
+    xpath: 'id("resultsList")'
+  }
+];
+var libly = liberator.plugins.libly;
+var $U = libly.$U;
+var logger = $U.getLogger("multi_requester");
+var mergedSiteinfo = {};
+var store = storage.newMap('plugins-multi_requester', {store: true});
+//}}}
+
+// Vimperator plugin command register {{{
+var CommandRegister = {
+  register: function(cmdClass, siteinfo) {
+    cmdClass.siteinfo = siteinfo;
+
+    commands.addUserCommand(
+      cmdClass.name,
+      cmdClass.description,
+      $U.bind(cmdClass, cmdClass.cmdAction),
+      {
+        completer: cmdClass.cmdCompleter || function(context, arg) {
+          if (arg.length > 1)
+            return;
+          context.title = [ "Name", "Descprition" ];
+          var sorted = siteinfo.sort(function(a, b)
+                         typeof liberator.globalVariables.multi_requester_order == "undefined" ||
+                         liberator.globalVariables.multi_requester_order == "date" ? store.get(b.name).lastPostTime - store.get(a.name).lastPostTime :
+                         liberator.globalVariables.multi_requester_order == "count" ? store.get(b.name).count - store.get(a.name).count :
+                         store.get(b.name).lastPostTime - store.get(a.name).lastPostTime);
+          var filters = context.filter.split(",");
+          var prefilters = filters.slice(0, filters.length - 1);
+          var prefilter = !prefilters.length ? "" : prefilters.join(",") + ",";
+          var subfilters = sorted.filter(function(s) prefilters.every(function(p) s.name != p));
+          var allSuggestions = subfilters.map(function(s) [prefilter + s.name, s.description]);
+          context.completions = context.filter
+            ? allSuggestions.filter(function(s) s[0].indexOf(context.filter) == 0)
+            : allSuggestions;
+        },
+        options: cmdClass.cmdOptions,
+        argCount: cmdClass.argCount || undefined,
+        bang: cmdClass.bang || true,
+        count: cmdClass.count || false
+      },
+      true // replace
+    );
+
+  },
+  addUserMaps: function(prefix, mapdef) {
+    mapdef.forEach(function([ key, command, bang, args ]) {
+      var cmd = prefix + (bang ? "! " : " ") + command + " ";
+      mappings.addUserMap(
+        [ modes.NORMAL, modes.VISUAL ],
+        [ key ],
+        "user defined mapping",
+        function() {
+          if (args) {
+            liberator.execute(cmd + args);
+          } else {
+            let sel = $U.getSelectedString();
+            if (sel.length) {
+              liberator.execute(cmd + sel);
+            } else {
+              commandline.open(":", cmd, modes.EX);
+            }
+          }
+        },
+        {
+          rhs: ":" + cmd,
+          norremap: true
+        }
+      );
+    });
+  }
+};
+//}}}
+
+// initial data access class {{{
+var DataAccess = {
+  getCommand: function() {
+    var c = liberator.globalVariables.multi_requester_command;
+    var ret;
+    if (typeof c == "string") {
+      ret = [ c ];
+    } else if (typeof c == "Array") {
+      ret = check;
+    } else {
+      ret = DEFAULT_COMMAND;
+    }
+    return ret;
+  },
+  getSiteInfo: function() {
+
+    var self = this;
+    var useWedata = typeof liberator.globalVariables.multi_requester_use_wedata == "undefined" ?
+                    true : $U.eval(liberator.globalVariables.multi_requester_use_wedata);
+
+    if (liberator.globalVariables.multi_requester_siteinfo) {
+      liberator.globalVariables.multi_requester_siteinfo.forEach(function(site) {
+        if (!mergedSiteinfo[site.name]) mergedSiteinfo[site.name] = {};
+        $U.extend(mergedSiteinfo[site.name], site);
+        if (!store.get(site.name)) {
+            store.set(site.name, { count: 0, lastPostTime: (new Date()).getTime() });
+            store.save();
+        }
+        if (site.map) {
+          CommandRegister.addUserMaps(MultiRequester.name[0],
+            [[ site.map, site.name, site.bang, site.args ]]);
+        }
+      });
+    }
+
+    SITEINFO.forEach(function(site) {
+      if (!mergedSiteinfo[site.name]) mergedSiteinfo[site.name] = {};
+      $U.extend(mergedSiteinfo[site.name], site);
+      if (!store.get(site.name)) {
+        store.set(site.name, { count: 0, lastPostTime: (new Date()).getTime() });
+        store.save();
+      }
+      if (site.map) {
+        CommandRegister.addUserMaps(MultiRequester.name[0],
+          [[ site.map, site.name, site.bang, site.args ]]);
+      }
+    });
+
+    if (useWedata) {
+      logger.log("use wedata");
+      var wedata = new libly.Wedata("Multi Requester");
+      wedata.getItems(24 * 60 * 60 * 1000,
+        function(item) {
+          var site = item.data;
+          if (mergedSiteinfo[site.name]) return;
+          mergedSiteinfo[site.name] = {};
+          $U.extend(mergedSiteinfo[site.name], site);
+          if (!store.get(site.name)) {
+            store.set(site.name, { count: 0, lastPostTime: (new Date()).getTime() });
+            store.save();
+          }
+        },
+        function(isSuccess, data) {
+          if (!isSuccess) return;
+          CommandRegister.register(MultiRequester, $U.A(mergedSiteinfo));
+        }
+      );
+    }
+
+    return $U.A(mergedSiteinfo);
+  }
+};
+//}}}
+
+// main controller {{{
+var MultiRequester = {
+  name: DataAccess.getCommand(),
+  description: "request, and display to the buffer",
+  defaultSites: liberator.globalVariables.multi_requester_default_sites,
+  doProcess: false,
+  requestNames: "",
+  requestCount: 0,
+  echoHash: {},
+  cmdAction: function(args) { //{{{
+
+    if (MultiRequester.doProcess) return;
+
+    var bang = args.bang;
+    var count = args.count;
+
+    var parsedArgs = this.parseArgs(args);
+    if (parsedArgs.count == 0) { return; } // do nothing
+
+    MultiRequester.doProcess = true;
+    MultiRequester.requestNames = parsedArgs.names;
+    MultiRequester.requestCount = 0;
+    MultiRequester.echoHash = {};
+    var siteinfo = parsedArgs.siteinfo;
+    for (let i = 0, len = parsedArgs.count; i < len; i++) {
+
+      let info = siteinfo[i];
+      let name = info.name;
+
+      let history = store.get(name);
+      history.count++;
+      history.lastPostTime = (new Date()).getTime();
+      store.set(name, history);
+      store.save();
+
+      let url = info.url;
+      // see: http://fifnel.com/2008/11/14/1980/
+      let srcEncode = info.srcEncode || "UTF-8";
+      let urlEncode = info.urlEncode || srcEncode;
+
+      let repStrCount = let (m = url.match(/%s/g)) (m && m.length);
+      if (repStrCount && !parsedArgs.strs.length) continue;
+
+      // via. lookupDictionary.js
+      let ttbu = Components.classes["@mozilla.org/intl/texttosuburi;1"]
+                 .getService(Components.interfaces.nsITextToSubURI);
+
+      let cnt = 0;
+      url = url.replace(/%s/g, function(m, i) ttbu.ConvertAndEscape(urlEncode,
+            (cnt >= parsedArgs.strs.length ? parsedArgs.strs[cnt - 1] :
+             cnt >= (repStrCount - 1) ? parsedArgs.strs.splice(cnt).join(' ') :
+             parsedArgs.strs[cnt++])));
+      logger.log(url + "[" + srcEncode + "][" + urlEncode + "]::" + info.xpath);
+
+      if (bang) {
+        liberator.open(url, liberator.NEW_TAB);
+      } else {
+        let req = new libly.Request(url, null, {
+          encoding: srcEncode,
+          siteinfo: info,
+          args: {
+            args: args,
+            bang: bang,
+            count: count
+          }
+        });
+        req.addEventListener("exception", $U.bind(this, this.onException));
+        req.addEventListener("success", $U.bind(this, this.onSuccess));
+        req.addEventListener("failure", $U.bind(this, this.onFailure));
+        req.get();
+        MultiRequester.requestCount++;
+      }
+    }
+
+    if (MultiRequester.requestCount) {
+      logger.echo("Loading " + parsedArgs.names + " ...", commandline.FORCE_SINGLELINE);
+    } else {
+      MultiRequester.doProcess = false;
+    }
+  },
+  // return {names: "", strs: [""], count: 0, siteinfo: [{}]}
+  parseArgs: function(args) {
+
+    var self = this;
+    var ret = {};
+    ret.names = "";
+    ret.strs = [];
+    ret.count = 0;
+    var sel = $U.getSelectedString();
+
+    if (args.length < 1 && !sel.length) return ret;
+
+    function parse(args, names) {
+      args = Array.concat(args);
+      ret.siteinfo = [];
+      ret.names = names || args.shift() || "";
+      ret.strs = (args.length < 1 ? [ sel.replace(/[\n\r]+/g, "") ] : args);
+
+      ret.names.split(",").forEach(function(name) {
+        var site = self.getSite(name);
+        if (site) {
+          ret.count++;
+          ret.siteinfo.push(site);
+        }
+      });
+    }
+
+    parse(args);
+
+    if (!ret.siteinfo.length && this.defaultSites)
+      parse(args, this.defaultSites);
+
+    return ret;
+  },
+  getSite: function(name) {
+    if (!name) this.siteinfo[0];
+    var ret = null;
+    this.siteinfo.forEach(function(s) {
+      if (s.name == name) ret = s;
+    });
+    return ret;
+  },//}}}
+  extractLink: function(res, extractLink) { //{{{
+
+    var el = res.getHTMLDocument(extractLink);
+    if (!el) throw "extract link failed.: extractLink -> " + extractLink;
+    var url = $U.pathToURL(el[0], res.req.url);
+    var req = new libly.Request(url, null, $U.extend(res.req.options, { extractLink: true }));
+    req.addEventListener("exception", $U.bind(this, this.onException));
+    req.addEventListener("success", $U.bind(this, this.onSuccess));
+    req.addEventListener("failure", $U.bind(this, this.onFailure));
+    req.get();
+    MultiRequester.requestCount++;
+    MultiRequester.doProcess = true;
+
+  },//}}}
+  onSuccess: function(res) { //{{{
+
+    if (!MultiRequester.doProcess) {
+      MultiRequester.requestCount = 0;
+      return;
+    }
+
+    logger.log("success!!: " + res.req.url);
+    MultiRequester.requestCount--;
+    if (MultiRequester.requestCount == 0) {
+      MultiRequester.doProcess = false;
+    }
+
+    var url, escapedUrl, xpath, doc, html, extractLink, ignoreTags;
+
+    try {
+
+      if (!res.isSuccess() || res.responseText == "") throw "response is fail or null";
+
+      url = res.req.url;
+      escapedUrl = util.escapeHTML(url);
+      xpath = res.req.options.siteinfo.xpath;
+      extractLink = res.req.options.siteinfo.extractLink;
+
+      if (extractLink && !res.req.options.extractLink) {
+        this.extractLink(res, extractLink);
+        return;
+      }
+      ignoreTags = [ "script" ].concat(libly.$U.A(res.req.options.siteinfo.ignoreTags));
+      doc = document.createElementNS(null, "div");
+      res.getHTMLDocument(xpath, null, ignoreTags, function(node, i) {
+        if (node.tagName.toLowerCase() != "html")
+          doc.appendChild(node);
+      });
+      if (!doc || !doc.childNodes.length) throw "XPath result is undefined or null.: XPath -> " + xpath;
+
+      $U.getNodesFromXPath("descendant-or-self::a | descendant-or-self::img", doc, function(node) {
+        var tagName = node.tagName.toLowerCase();
+        if (tagName == "a") {
+          node.href = $U.pathToURL(node, url, res.doc);
+        } else if (tagName == "img") {
+          node.src = $U.pathToURL(node, url, res.doc);
+        }
+      });
+
+      html = '<a href="' + escapedUrl + '" class="hl-Title" target="_self">' + escapedUrl + '</a>' +
+           $U.xmlSerialize(doc);
+
+      MultiRequester.echoHash[res.req.options.siteinfo.name] = html;
+
+    } catch (e) {
+      logger.log("error!!: " + e);
+      MultiRequester.echoHash[res.req.options.siteinfo.name] =
+              '<span style="color: red;">error!!: ' + e + '</span>';
+    }
+
+    if (MultiRequester.requestCount == 0) {
+      let echoList = [];
+      MultiRequester.requestNames.split(",").forEach(function(name) {
+        echoList.push(MultiRequester.echoHash[name]);
+      });
+      html = '<div style="white-space:normal;"><base href="' + escapedUrl + '"/>' +
+             echoList.join("") +
+             '</div>';
+      try { logger.echo(new XMLList(html)); } catch (e) { logger.log(e); logger.echo(html); }
+    }
+
+  },
+  onFailure: function(res) {
+    MultiRequester.doProcess = false;
+    logger.echoerr("request failure!!: " + res.statusText);
+  },
+  onException: function(e) {
+    MultiRequester.doProcess = false;
+    logger.echoerr("exception!!: " + e);
+  }//}}}
+};
+//}}}
+
+// boot strap {{{
+CommandRegister.register(MultiRequester, DataAccess.getSiteInfo());
+if (liberator.globalVariables.multi_requester_mappings) {
+  CommandRegister.addUserMaps(MultiRequester.name[0], liberator.globalVariables.multi_requester_mappings);
+}
+//}}}
+
+return MultiRequester;
+
+})();
+// vim: set fdm=marker sw=2 ts=2 sts=0 et:
+