From aafe4912ff7050d1824b920c810934246e3b749a Mon Sep 17 00:00:00 2001 From: PHO Date: Tue, 4 Aug 2009 10:53:18 +0900 Subject: [PATCH] Auto commit by The Sugar System. --- dot-files/_vimperator/plugin/_libly_js | 678 ++++++++++++++++++ .../_vimperator/plugin/multi_requester_js | 495 +++++++++++++ tools/import.pl | 4 +- 3 files changed, 1176 insertions(+), 1 deletion(-) create mode 100644 dot-files/_vimperator/plugin/_libly_js create mode 100644 dot-files/_vimperator/plugin/multi_requester_js diff --git a/dot-files/_vimperator/plugin/_libly_js b/dot-files/_vimperator/plugin/_libly_js new file mode 100644 index 0000000..6d547a8 --- /dev/null +++ b/dot-files/_vimperator/plugin/_libly_js @@ -0,0 +1,678 @@ +/*** BEGIN LICENSE BLOCK {{{ + Copyright (c) 2008 suVene + + distributable under the terms of an MIT-style license. + http://www.opensource.jp/licenses/mit-license.html +}}} END LICENSE BLOCK ***/ +// PLUGIN_INFO//{{{ +var PLUGIN_INFO = + + libly(filename _libly.js) + Vimperator plugins library? + 適当なライブラリっぽいものたち。 + suVene + MIT + 0.1.24 + 1.2 + 2.0pre + http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/_libly.js + ※1 + ※1 の文字列を取得します。 +stripTags(str, tags): + str から tags で指定されたタグを取り除いて返却します。 + tags は文字列、または配列で指定して下さい。 +createHTMLDocument(str, xmlns): + 引数 str より、HTMLFragment を作成します。 +getFirstNodeFromXPath(xpath, context): + xpath を評価しオブジェクトをを返却します。 +getNodesFromXPath(xpath, context, callback, thisObj): + xpath を評価し snapshot の配列を返却します。 +xmlSerialize(xml): + xml を文字列化します。 +xmlToDom(node, doc, nodes): + for vimperator1.2. + @see vimperator2.0pre util. +getElementPosition(elem): + elem の offset を返却します。 + return {top: 0, left: 0} +toStyleText(style): + スタイルが格納されているオブジェクトを + >|| + position: fixed; + left: 10px; + ||< + のような文字列に変換します。 + +== Object Request == +Request(url, headers, options): + コンストラクタ + url: + HTTPリクエスト先のURL + headers: + 以下のようにHTTPヘッダの値を指定できる(省略可) + >|| + { + 'Referrer' : 'http://example.com/' + } + ||< + 以下の値はデフォルトで設定される('Content-type'はPOST時のみ) + >|| + { + 'Accept': 'text/javascript, application/javascript, text/html, application/xhtml+xml, application/xml, text/xml, */*;q=0.1', + 'Content-type': 'application/x-www-form-urlencoded; charset=' + options.encodingの値 + } + ||< + + options: + オプションとして以下のようなオブジェクトを指定できる(省略可) + asynchronous: + true: 同期モード/false: 非同期モード(デフォルト:true) + encoding: + エンコーディング(デフォルト: 'UTF-8') + username: + BASIC認証時のuser名 + password: + BASIC認証時のパスワード + postBody: + POSTメソッドにより送信するbody +addEventLister(name, func): + イベントリスナを登録する。 + name: + 'onSuccess': + 成功時 + 'onFailure': + 失敗を表すステータスコードが返ってきた時 + 'onException': + 例外発生時 + func: + イベント発火時の処理 + 引数として以下Responseオブジェクトが渡される +get(): + GETメソッドによりHTTPリクエストを発行する。 +post(): + POSTメソッドによりHTTPリクエストを発行する。 + +== Object Response == +HTTPレスポンスを表すオブジェクト +req: + レスポンスと対となるRequestオブジェクト +doc: + レスポンスから生成されたHTMLDocumentオブジェクト +isSuccess(): + ステータスコードが成功を表していればtrue、失敗であればfalse +getStatus(): + ステータスコードを取得する +getStatusText(): + ステータを表す文字列を取得する +getHTMLDocument(xpath, xmlns, ignoreTags, callback, thisObj): + レスポンスからHTMLDocumentオブジェクトを生成し、xpath を評価した結果の snapshot の配列を返す + +== Object Wedata == +~/vimperator/info/profile_name/plugins-libly-wedata-????? +に store されます。 +getItems(expire, itemCallback, finalCallback): + インスタンス作成時に指定した dbname から、item を読込みます。 +=== TODO === +clearCache: + wedata 読込み成功したら、強制的にキャッシュと置き換えるの作って! + + ]]> +; +//}}} +//if (!liberator.plugins.libly) { + +liberator.plugins.libly = {}; +var libly = liberator.plugins.libly; + +libly.$U = {//{{{ + // Logger {{{ + getLogger: function(prefix) { + return new function() { + this.log = function(msg, level) { + if (typeof msg == 'object') msg = util.objectToString(msg); + liberator.log(libly.$U.dateFormat(new Date()) + ': ' + (prefix || '') + ': ' + msg, (level || 0)); + }; + this.echo = function(msg, flg) { + flg = flg || commandline.FORCE_MULTILINE; + // this.log(msg); + liberator.echo(msg, flg); + }; + this.echoerr = function(msg) { + this.log('error: ' + msg); + liberator.echoerr(msg); + }; + } + }, + // }}} + // Object Utility {{{ + extend: function(dst, src) { + for (let prop in src) + dst[prop] = src[prop]; + return dst; + }, + A: function(iterable) { + var ret = []; + if (!iterable) return ret; + if (typeof iterable == 'string') return [iterable]; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) return iterable.toArray(); + if (typeof iterable.length != 'undefined') { + for (let i = 0, len = iterable.length; i < len; ret.push(iterable[i++])); + } else { + for each (let item in iterable) ret.push(item); + } + return ret; + }, + around: function around (obj, name, func) { + let next = obj[name]; + let current = obj[name] = function () { + let self = this, args = arguments; + return func.call(self, function () next.apply(self, args), args); + }; + return [next, current]; + }, + bind: function(obj, func) { + return function() { + return func.apply(obj, arguments); + } + }, + eval: function(text) { + var fnc = window.eval; + var sandbox; + try { + sandbox = new Components.utils.Sandbox("about:blank"); + if (Components.utils.evalInSandbox('true', sandbox) === true) { + fnc = function(text) { return Components.utils.evalInSandbox(text, sandbox); }; + } + } catch (e) { liberator.log('warning: _libly.js is working with unsafe sandbox.'); } + + return fnc(text); + }, + evalJson: function(str, toRemove) { + var json; + try { + json = Components.classes['@mozilla.org/dom/json;1'].getService(Components.interfaces.nsIJSON); + if (toRemove) str = str.substring(1, str.length - 1); + return json.decode(str); + } catch (e) { return null; } + }, + dateFormat: function(dtm, fmt) { + var d = { + y: dtm.getFullYear(), + M: dtm.getMonth() + 1, + d: dtm.getDate(), + h: dtm.getHours(), + m: dtm.getMinutes(), + s: dtm.getSeconds(), + '%': '%' + }; + for (let [n, v] in Iterator(d)) { + if (v < 10) + d[n] = '0' + v; + } + return (fmt || '%y/%M/%d %h:%m:%s').replace(/%([yMdhms%])/g, function (_, n) d[n]); + }, + /** + * example) + * $U.runnable(function(resume) { + * // execute asynchronous function. + * // goto next yield; + * var val = yield setTimeout(function() { resume('value!'), 1000) }); + * alert(val); // value! + * yield; + * }); + */ + runnable: function(generator) { + var it = generator(function(value) { + try { it.send(value); } catch (e) {} + }); + it.next(); + }, + // }}} + // Browser {{{ + getSelectedString: function() { + return (new XPCNativeWrapper(window.content.window)).getSelection().toString(); + }, + getUserAndPassword: function(hostname, formSubmitURL, username) { + var passwordManager, logins; + try { + passwordManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager); + logins = passwordManager.findLogins({}, hostname, formSubmitURL, null); + if (logins.length) { + if (username) { + for (let i = 0, len = logins.lengh; i < len; i++) { + if (logins[i].username == username) + return [logins[i].username, logins[i].password] + } + liberator.log(this.dateFormat(new Date()) +': [getUserAndPassword] username notfound'); + //throw 'username notfound.'; + return []; + } else { + return [logins[0].username, logins[0].password]; + } + } else { + liberator.log(this.dateFormat(new Date()) + ': [getUserAndPassword] account notfound'); + return []; + } + } catch (e) { + liberator.log(this.dateFormat(new Date()) + ': [getUserAndPassword] error: ' + e, 0); + return null; + } + }, + // }}} + // System {{{ + readDirectory: function(path, filter, func) { + var d = io.getFile(path); + if (d.exists() && d.isDirectory()) { + let enm = d.directoryEntries; + let flg = false; + while (enm.hasMoreElements()) { + let item = enm.getNext(); + item.QueryInterface(Components.interfaces.nsIFile); + flg = false; + if (typeof filter == 'string') { + if ((new RegExp(filter)).test(item.leafName)) flg = true; + } else if (typeof filter == 'function') { + flg = filter(item); + } + if (flg) func(item); + } + } + }, + // }}} + // HTML, XML, DOM, E4X {{{ + pathToURL: function(a, baseURL, doc) { + if (!a) return ''; + var XHTML_NS = "http://www.w3.org/1999/xhtml"; + var XML_NS = "http://www.w3.org/XML/1998/namespace"; + //var path = (a.href || a.getAttribute('src') || a.action || a.value || a); + var path = (a.getAttribute('href') || a.getAttribute('src') || a.action || a.value || a); + if (/^https?:\/\//.test(path)) return path; + var link = (doc || window.content.documtent).createElementNS(XHTML_NS, 'a'); + link.setAttributeNS(XML_NS, 'xml:base', baseURL); + link.href = path; + return link.href; + }, + getHTMLFragment: function(html) { + if (!html) return html; + return html.replace(/^[\s\S]*?]*)?>|<\/html[ \t\r\n]*>[\S\s]*$/ig, ''); + }, + stripTags: function(str, tags) { + var ignoreTags = '(?:' + [].concat(tags).join('|') + ')'; + return str.replace(new RegExp('<' + ignoreTags + '(?:[ \\t\\n\\r][^>]*|/)?>([\\S\\s]*?)<\/' + ignoreTags + '[ \\t\\r\\n]*>', 'ig'), ''); + }, + createHTMLDocument: function(str, xmlns, doc) { + let root = document.createElementNS("http://www.w3.org/1999/xhtml", "html"); + let uhService = Cc["@mozilla.org/feed-unescapehtml;1"].getService(Ci.nsIScriptableUnescapeHTML); + let text = str.replace(/^[\s\S]*?]*)?>[\s]*|<\/body[ \t\r\n]*>[\S\s]*$/ig, ''); + let fragment = uhService.parseFragment(text, false, null, root); + let htmlFragment = document.implementation.createDocument(null, 'html', null); + htmlFragment.documentElement.appendChild(htmlFragment.importNode(fragment,true)); + return htmlFragment; + /* うまく動いていない場合はこちらに戻してください + doc = doc || window.content.document; + var htmlFragment = doc.implementation.createDocument(null, 'html', null); + var range = doc.createRange(); + range.setStartAfter(doc.body); + htmlFragment.documentElement.appendChild(htmlFragment.importNode(range.createContextualFragment(str), true)); + return htmlFragment; + */ + }, + getFirstNodeFromXPath: function(xpath, context) { + if (!xpath) return null; + context = context || window.content.document; + var result = (context.ownerDocument || context).evaluate(xpath, context, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null); + return result.singleNodeValue || null; + }, + getNodesFromXPath: function(xpath, context, callback, thisObj) { + var ret = []; + if (!xpath) return ret; + context = context || window.content.document; + var nodesSnapshot = (context.ownerDocument || context).evaluate(xpath, context, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + for (let i = 0, l = nodesSnapshot.snapshotLength; i < l; i++) { + if (typeof callback == 'function') callback.call(thisObj, nodesSnapshot.snapshotItem(i), i); + ret.push(nodesSnapshot.snapshotItem(i)); + } + return ret; + }, + xmlSerialize: function(xml) { + try { + return (new XMLSerializer()).serializeToString(xml) + .replace(//g, '') + .replace(/<\s*\/?\s*\w+/g, function(all) all.toLowerCase()); + } catch (e) { return '' } + }, + xmlToDom: function xmlToDom(node, doc, nodes) + { + XML.prettyPrinting = false; + switch (node.nodeKind()) + { + case "text": + return doc.createTextNode(node); + case "element": + let domnode = doc.createElementNS(node.namespace(), node.localName()); + for each (let attr in node.@*) + domnode.setAttributeNS(attr.name() == "highlight" ? NS.uri : attr.namespace(), attr.name(), String(attr)); + for each (let child in node.*) + domnode.appendChild(arguments.callee(child, doc, nodes)); + if (nodes && node.@key) + nodes[node.@key] = domnode; + return domnode; + } + }, + getElementPosition: function(elem) { + var offsetTrail = elem; + var offsetLeft = 0; + var offsetTop = 0; + while (offsetTrail) { + offsetLeft += offsetTrail.offsetLeft; + offsetTop += offsetTrail.offsetTop; + offsetTrail = offsetTrail.offsetParent; + } + offsetTop = offsetTop || null; + offsetLeft = offsetLeft || null; + return {top: offsetTop, left: offsetLeft}; + }, + toStyleText: function(style) { + var result = ''; + for (let name in style) { + result += name.replace(/[A-Z]/g, function (c) ('-' + c.toLowerCase())) + + ': ' + + style[name] + + ';\n'; + } + return result; + } + // }}} +}; +//}}} + +libly.Request = function() {//{{{ + this.initialize.apply(this, arguments); +}; +libly.Request.EVENTS = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; +libly.Request.requestCount = 0; +libly.Request.prototype = { + initialize: function(url, headers, options) { + this.url = url; + this.headers = headers || {}; + this.options = libly.$U.extend({ + asynchronous: true, + encoding: 'UTF-8' + }, options || {}); + this.observers = {}; + }, + addEventListener: function(name, func) { + try { + if (typeof this.observers[name] == 'undefined') this.observers[name] = []; + this.observers[name].push(func); + } catch (e) { + if (!this.fireEvent('onException', new libly.Response(this), e)) throw e; + } + }, + fireEvent: function(name, args, asynchronous) { + if (!(this.observers[name] instanceof Array)) return false; + this.observers[name].forEach(function(event) { + if (asynchronous) { + setTimeout(event, 10, args); + } else { + event(args); + } + }); + return true; + }, + _complete: false, + _request: function(method) { + + try { + libly.Request.requestCount++; + + this.method = method; + this.transport = new XMLHttpRequest(); + this.transport.open(method, this.url, this.options.asynchronous, this.options.username, this.options.password); + + this.transport.onreadystatechange = libly.$U.bind(this, this._onStateChange); + this.setRequestHeaders(); + this.transport.overrideMimeType('text/html; charset=' + this.options.encoding); + + this.body = this.method == 'POST' ? this.options.postBody : null; + + this.transport.send(this.body); + + // Force Firefox to handle ready state 4 for synchronous requests + if (!this.options.asynchronous && this.transport.overrideMimeType) + this._onStateChange(); + + } catch (e) { + if (!this.fireEvent('onException', new libly.Response(this), e)) throw e; + } + }, + _onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !(readyState == 4 && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0; } + }, + isSuccess: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + respondToReadyState: function(readyState) { + var state = libly.Request.EVENTS[readyState]; + var res = new libly.Response(this); + + if (state == 'Complete') { + libly.Request.requestCount--; + try { + this._complete = true; + this.fireEvent('on' + (this.isSuccess() ? 'Success' : 'Failure'), res, this.options.asynchronous); + } catch (e) { + if (!this.fireEvent('onException', res, e)) throw e; + } + } + }, + setRequestHeaders: function() { + var headers = { + 'Accept': 'text/javascript, application/javascript, text/html, application/xhtml+xml, application/xml, text/xml, */*;q=0.1' + }; + + if (this.method == 'POST') { + headers['Content-type'] = 'application/x-www-form-urlencoded' + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + if (this.transport.overrideMimeType) { + let year = parseInt((navigator.userAgent.match(/\bGecko\/(\d{4})/) || [0, 2005])[1], 10); + if (0 < year && year < 2005) + headers['Connection'] = 'close'; + } + } + + for (let key in this.headers) + if (this.headers.hasOwnProperty(key)) headers[key] = this.headers[key]; + + for (let name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + get: function() { + this._request('GET'); + }, + post: function() { + this._request('POST'); + } +};//}}} + +libly.Response = function() {//{{{ + this.initialize.apply(this, arguments); +}; +libly.Response.prototype = { + initialize: function(req) { + this.req = req; + this.transport = req.transport; + this.isSuccess = req.isSuccess; + this.readyState = this.transport.readyState; + + if (this.readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = (this.transport.responseText == null) ? '' : this.transport.responseText; + } + + this.doc = null; + this.htmlFragmentstr = ''; + }, + status: 0, + statusText: '', + getStatus: libly.Request.prototype.getStatus, + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return ''; } + }, + getHTMLDocument: function(xpath, xmlns, ignoreTags, callback, thisObj) { + if (!this.doc) { + //if (doc.documentElement.nodeName != 'HTML') { + // return new DOMParser().parseFromString(str, 'application/xhtml+xml'); + //} + this.htmlFragmentstr = libly.$U.getHTMLFragment(this.responseText); + this.htmlStripScriptFragmentstr = libly.$U.stripTags(this.htmlFragmentstr, ignoreTags); + this.doc = libly.$U.createHTMLDocument(this.htmlStripScriptFragmentstr, xmlns); + } + if (!xpath) xpath = '//*'; + return libly.$U.getNodesFromXPath(xpath, this.doc, callback, thisObj); + } +}; +//}}} + +libly.Wedata = function(dbname) { // {{{ + this.initialize.apply(this, arguments); +}; +libly.Wedata.prototype = { + initialize: function(dbname) { + this.HOST_NAME = 'http://wedata.net/'; + this.dbname = dbname; + this.logger = libly.$U.getLogger('libly.Wedata'); + }, + getItems: function(expire, itemCallback, finalCallback) { + + var logger = this.logger; + var STORE_KEY = 'plugins-libly-wedata-' + this.dbname + '-items'; + var store = storage.newMap(STORE_KEY, true); + var cache = store && store.get('data'); + + if (store && cache && new Date(store.get('expire')) > new Date()) { + logger.log('return cache. '); + cache.forEach(function(item) { if (typeof itemCallback == 'function') itemCallback(item); }); + if (typeof finalCallback == 'function') + finalCallback(true, cache); + return; + } + + expire = expire || 0; + + function errDispatcher(msg, cache) { + if (cache) { + logger.log('return cache. -> ' + msg); + cache.forEach(function(item) { if (typeof itemCallback == 'function') itemCallback(item); }); + if (typeof finalCallback == 'function') + finalCallback(true, cache); + } else { + logger.log(msg + ': cache notfound.'); + if (typeof finalCallback == 'function') + finalCallback(false, msg); + } + } + + var req = new libly.Request(this.HOST_NAME + 'databases/' + this.dbname + '/items.json'); + req.addEventListener('onSuccess', libly.$U.bind(this, function(res) { + var text = res.responseText; + if (!text) { + errDispatcher('respons is null.', cache); + return; + } + var json = libly.$U.evalJson(text); + if (!json) { + errDispatcher('failed eval json.', cache); + return; + } + logger.log('success get wedata.'); + store.set('expire', new Date(new Date().getTime() + expire).toString()); + store.set('data', json); + store.save(); + json.forEach(function(item) { if (typeof itemCallback == 'function') itemCallback(item); }); + if (typeof finalCallback == 'function') + finalCallback(true, json); + })); + req.addEventListener('onFailure', function() errDispatcher('onFailure', cache)); + req.addEventListener('onException', function() errDispatcher('onException', cache)); + req.get(); + } +}; +//}}} + +//} +// vim: set fdm=marker sw=4 ts=4 sts=0 et: + diff --git a/dot-files/_vimperator/plugin/multi_requester_js b/dot-files/_vimperator/plugin/multi_requester_js new file mode 100644 index 0000000..88f24e0 --- /dev/null +++ b/dot-files/_vimperator/plugin/multi_requester_js @@ -0,0 +1,495 @@ +/*** BEGIN LICENSE BLOCK {{{ + Copyright (c) 2008 suVene + + distributable under the terms of an MIT-style license. + http://www.opensource.jp/licenses/mit-license.html +}}} END LICENSE BLOCK ***/ +// PLUGIN_INFO//{{{ +var PLUGIN_INFO = + + {NAME} + request, and the result is displayed to the buffer. + リクエストの結果をバッファに出力する。 + suVene + 0.4.15 + MIT + 2.0pre + 2.1pre + http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/multi_requester.js + || +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 <|| +javascript <|| +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" を設定してください。 + + ]]> +; +//}}} +(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("resultList")' + } +]; +var libly = liberator.plugins.libly; +var $U = libly.$U; +var logger = $U.getLogger("multi_requester"); +var mergedSiteinfo = {}; +var store = storage.newMap('plugins-multi_requester', 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%20Requester"); + 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("onException", $U.bind(this, this.onException)); + req.addEventListener("onSuccess", $U.bind(this, this.onSuccess)); + req.addEventListener("onFailure", $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("onException", $U.bind(this, this.onException)); + req.addEventListener("onSuccess", $U.bind(this, this.onSuccess)); + req.addEventListener("onFailure", $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 = '' + escapedUrl + '' + + $U.xmlSerialize(doc); + + MultiRequester.echoHash[res.req.options.siteinfo.name] = html; + + } catch (e) { + logger.log("error!!: " + e); + MultiRequester.echoHash[res.req.options.siteinfo.name] = + 'error!!: ' + e + ''; + } + + if (MultiRequester.requestCount == 0) { + let echoList = []; + MultiRequester.requestNames.split(",").forEach(function(name) { + echoList.push(MultiRequester.echoHash[name]); + }); + html = '
' + + echoList.join("") + + '
'; + 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: + diff --git a/tools/import.pl b/tools/import.pl index 5a1e0dc..8946e09 100644 --- a/tools/import.pl +++ b/tools/import.pl @@ -11,7 +11,9 @@ sub main { while (defined(my $arg = <>)) { chomp $arg; - my $rel = File::Spec->abs2rel($arg, $ENV{HOME}); + my $rel = File::Spec->file_name_is_absolute($arg) + ? File::Spec->abs2rel($arg, $ENV{HOME}) + : $arg; my $abs = File::Spec->rel2abs($rel, $ENV{HOME}); my $saved = rel2saved($rel); -- 2.40.0