From bbeac9e40d1a6958040a00cca65e8f26b9fa8c41 Mon Sep 17 00:00:00 2001
From: Gabriel Ebner
Date: Sat, 30 Aug 2014 07:29:19 +0200
Subject: [PATCH] vimperator
---
Makefile | 2 +-
vimperator/plugin/_libly.js | 737 ++++++++++++++++++++++++++++
vimperator/plugin/feedSomeKeys_3.js | 726 +++++++++++++++++++++++++++
vimperator/plugin/wallabag.js | 35 ++
vimperatorrc | 50 ++
vimrc | 1 +
6 files changed, 1550 insertions(+), 1 deletion(-)
create mode 100644 vimperator/plugin/_libly.js
create mode 100644 vimperator/plugin/feedSomeKeys_3.js
create mode 100644 vimperator/plugin/wallabag.js
create mode 100644 vimperatorrc
diff --git a/Makefile b/Makefile
index 56c72c7..92739ec 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
FILES = bashrc vimrc zshrc emacs.el gitconfig screenrc commonshrc \
- gnomerc gvimrc muttrc pentadactylrc
+ gnomerc gvimrc muttrc pentadactylrc vimperatorrc
FILES2 = msmtprc
.PHONY: install clean check
diff --git a/vimperator/plugin/_libly.js b/vimperator/plugin/_libly.js
new file mode 100644
index 0000000..be989d7
--- /dev/null
+++ b/vimperator/plugin/_libly.js
@@ -0,0 +1,737 @@
+/*** BEGIN LICENSE BLOCK {{{
+ Copyright (c) 2008 suVene
+ Copyright (c) 2008-2011 anekos
+
+ 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 = xml`
+
+ libly(filename _libly.js)
+ Vimperator plugins library?
+ 適当なライブラリっぽいものたち。
+ suVene
+ anekos
+ MIT
+ 0.1.38
+ 2.3pre
+ https://github.com/vimpr/vimperator-plugins/raw/master/_libly.js
+ ||
+ {
+ original: オリジナルの関数
+ current: 現在の関数
+ restore: 元に戻すための関数
+ }
+ ||<
+bind(obj, func):
+ func に obj を bind します。
+ func内からは this で obj が参照できるようになります。
+eval(text):
+ Sandbox による、window.eval を極力利用するようにします。
+ Snadbox が利用できない場合は、unsafe な window の eval が直接利用されます。
+evalJson(str, toRemove):
+ str を decode します。
+ toRemove が true の場合、文字列の前後を1文字削除します。
+ "(key:value)" 形式の場合などに true を指定して下さい。
+dateFormat(dtm, fmt):
+ Date型インスタンスを、指定されたフォーマットで文字列に変換します。
+ fmt を省略した場合、"%y/%M/%d %h:%m:%s" となります。
+runnable(generator):
+ gererator を実行し、再帰的に resume する為の引数を渡します。
+
+== Browser ==
+getSelectedString:
+ window の選択文字列を返却します。
+getUserAndPassword(hostname, formSubmitURL, username):
+ login-manager から [username, password] を取得します。
+ 引数の username が省略された場合、検索された 1件目を返却します。
+ データが存在しない場合は、null を返却します。
+
+== System ==
+readDirectory(path, fileter, func):
+ path で指定したディレクトリから、filter で指定された正規表現に match する場合、
+ func をファイル名を引数にコールバックします。
+ filter は Function を指定することも可能です。
+
+== HTML, XML, DOM, E4X ==
+pathToURL(a, baseURL, doc):
+ 相対パスを絶対パスに変換します。
+getHTMLFragment(html):
+ ※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ヘッダの値を指定できる(省略可)
+ >||
+ {
+ 'Referer' : '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
+addEventListener(name, func):
+ イベントリスナを登録する。
+ name:
+ 'success':
+ 成功時
+ 'failure':
+ 失敗を表すステータスコードが返ってきた時
+ 'exception':
+ 例外発生時
+ 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;
+
+// XXX for backward compatibillity
+function fixEventName(name) {
+ return name.replace(/^on/, '').toLowerCase();
+}
+
+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 () {
+ function getPluginPath () {
+ let pluginPath;
+ Error('hoge').stack.split(/\n/).some(
+ function (s)
+ let (m = s.match(/-> liberator:\/\/template\/chrome:\/\/liberator\/content\/liberator\.js -> (.+):\d+$/))
+ (m && (pluginPath = m[1].replace(/\?.*$/, '')))
+ );
+ return pluginPath;
+ }
+
+ let restores = {};
+
+ return function (obj, name, func, autoRestore) {
+ let original;
+ let restore = function () obj[name] = original;
+ if (autoRestore) {
+ let pluginPath = getPluginPath();
+ if (pluginPath) {
+ restores[pluginPath] =
+ (restores[pluginPath] || []).filter(
+ function (res) (
+ res.object != obj ||
+ res.name != name ||
+ (res.restore() && false)
+ )
+ );
+ restores[pluginPath].push({
+ object: obj,
+ name: name,
+ restore: restore
+ });
+ } else {
+ liberator.echoerr('getPluginPath failed');
+ }
+ }
+ original = obj[name];
+ let current = obj[name] = function () {
+ let self = this, args = arguments;
+ return func.call(self, function (_args) original.apply(self, _args || args), args);
+ };
+ libly.$U.extend(current, {original: original && original.original || original, restore: restore});
+ return libly.$U.extend({
+ original: original,
+ current: current,
+ restore: restore
+ }, [original, 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.File(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 doctype = document.implementation.createDocumentType('html', '-//W3C//DTD HTML 4.01//EN', 'http://www.w3.org/TR/html4/strict.dtd');
+ let htmlFragment = document.implementation.createDocument(null, 'html', doctype);
+ 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)
+ {
+ return util.xmlToDom(node, doc, nodes);
+ },
+ 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) {
+ name = fixEventName(name);
+ try {
+ if (typeof this.observers[name] == 'undefined') this.observers[name] = [];
+ this.observers[name].push(func);
+ } catch (e) {
+ if (!this.fireEvent('exception', new libly.Response(this), e)) throw e;
+ }
+ },
+ fireEvent: function(name, args, asynchronous) {
+ name = fixEventName(name);
+ 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);
+
+ var stateChangeException;
+ this.transport.onreadystatechange = libly.$U.bind(this, function () {
+ try {
+ this._onStateChange();
+ } catch (e) {
+ stateChangeException = e;
+ }
+ });
+ this.setRequestHeaders();
+ this.transport.overrideMimeType(this.options.mimetype || 'text/html; charset=' + this.options.encoding);
+
+ this.body = this.method == 'POST' ? this.options.postBody : null;
+
+ this.transport.send(this.body);
+
+ if (!this.options.asynchronous && stateChangeException) throw stateChangeException;
+
+ // Force Firefox to handle ready state 4 for synchronous requests
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
+ this._onStateChange();
+
+ } catch (e) {
+ if (!this.fireEvent('exception', 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(this.isSuccess() ? 'success' : 'failure', res, this.options.asynchronous);
+ } catch (e) {
+ if (!this.fireEvent('exception', 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.responseXML = this.transport.responseXML;
+ }
+
+ 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-' + encodeURIComponent(this.dbname) + '-items';
+ var store = storage.newMap(STORE_KEY, {store: 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/' + encodeURIComponent(this.dbname) + '/items.json');
+ req.addEventListener('success', libly.$U.bind(this, function(res) {
+ var text = res.responseText;
+ if (!text) {
+ errDispatcher('response 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('failure', function() errDispatcher('onFailure', cache));
+ req.addEventListener('exception', function() errDispatcher('onException', cache));
+ req.get();
+ }
+};
+//}}}
+
+//}
+// vim: set fdm=marker sw=4 ts=4 sts=0 et:
+
diff --git a/vimperator/plugin/feedSomeKeys_3.js b/vimperator/plugin/feedSomeKeys_3.js
new file mode 100644
index 0000000..fd08ec6
--- /dev/null
+++ b/vimperator/plugin/feedSomeKeys_3.js
@@ -0,0 +1,726 @@
+/* NEW BSD LICENSE {{{
+Copyright (c) 2010-2011, anekos.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ 3. The names of the authors may not be used to endorse or promote products
+ derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+THE POSSIBILITY OF SUCH DAMAGE.
+
+
+###################################################################################
+# http://sourceforge.jp/projects/opensource/wiki/licenses%2Fnew_BSD_license #
+# に参考になる日本語訳がありますが、有効なのは上記英文となります。 #
+###################################################################################
+
+}}} */
+
+// INFO {{{
+let INFO =
+xml`
+ anekos
+ New BSD License
+
+
+ Feed key events directly into web contents.
+
+ -
+ :fmap
+ :fmap -events=eventnamelist -xpath=xpath -frame=framenumber -urls=urlpattern -modes=modes lhs rhs
+
+
+ Define one mapping.
+
+
+ If -urls=urlpattern is given,
+ the mappings becomes effective mappings only on the page specifed by urlpattern.
+
+
+
+ -
+ :fmaps
+ :fmaps -events=eventnamelist -xpath=xpath -frame=framenumber -urls=urlpattern -pprefix=prefix -modes=modes mappingpair ....
+
+
+ Two or more mappings are defined at once.
+ mappingpair is a pair of key names separated by ",".
+
e.g. "<Leader><S-j>,j"
+
+
+ If -urls=urlpattern is given,
+ the mappings becomes effective mappings only on the page specifed by urlpattern.
+
+
+
+ -
+ :fmapc
+ :fmapc! -modes=modes urlpattern
+
+
+ Remove the mappings matched with urlpattern.
+ If "!" is given, remove all mappings.
+
+
+
+ -
+ :funmap
+ :funmap -urls=urlpattern -modes=modes lhs
+
+
+ Remove the mappings.
+
+
+ If you wish to remove url-local mappings, give -urls=urlpattern.
+
+
+
+ urlpattern
+
+ The value of urlpattern should be regular expression.
+
+ xpath
+
+ The XPath for a target element.
+
+ framenumber
+
+ The number of a target frame.
+ Refer the completion for this number.
+
+ eventnamelist
+
+ eventnamelist is the list constructed with the below values.
+
+
+ - keypress
+ - keydown
+ - keyup
+ - vkeypress
+ - vkeydown
+ - vkeyup
+
+ "v..." values use virtual key code.
+ The event is generated in the order of writing of each key.
+ The default value of this option is "keypress".
+ modes
+
+ List of mapping modes. (Default is NORMAL mode)
+
+ fmaps examples for .vimperatorrc
+ If you input directly these commands in vimperator commandline, remove the ":lazy".
+
+:command! -nargs=+ lazy autocmd VimperatorEnter .* <args>
+:lazy fmaps -u='mail\.google\.com/mail' c / j k n p o u e x s r a # [ ] ? gi gs gt gd ga gc
+:lazy fmaps -u='mail\.google\.com/mail/.*/[0-9a-f]+$' c / j,n k,p n,j p,k o u e x s r a # [ ] ? gi gs gt gd ga gc
+:lazy fmaps -u='www\.google\.co\.jp/reader' -events=vkeypress j k n p m s v A r S N P X O gh ga gs gt gu u / ? J K
+:lazy fmaps -u='(fastladder|livedoor)\.com/reader' j k s a p o v c i,p <Space> <S-Space> z b < > q w e,g
+:lazy fmaps -u='https?://www\.rememberthemilk\.com/home/' j k m i c t ? d F,f G,g S,s L,l Y,y H,h M,m <Del> <C-S-Left> <C-S-Right>
+:lazy fmaps -u='http://code.google.com/p/vimperator-labs/issues/list' o j k
+:lazy fmaps -u='http://code.google.com/p/vimperator-labs/issues/detail' u
+
+
+
+ anekos
+ New BSD License
+
+
+ Web コンテンツに直接キーイベントを送ります。
+
+ -
+ :fmap
+ :fmap -events=eventnamelist -xpath=xpath -frame=framenumber -urls=urlpattern -modes=modes lhs rhs
+
+
+ マッピングを一つ定義します。
+
+
+ -urls=urlpattern が与えられたとき、
+ そのマッピングは urlpattern で指定されたページのみで有効になります。
+
+
+
+ -
+ :fmaps
+ :fmaps -events=eventnamelist -xpath=xpath -frame=framenumber -urls=urlpattern -pprefix=prefix -modes=modes mappingpair ....
+
+
+ 一度に複数のマッピングを定義できます。
+ mappingpair は、"," で区切られたキー名の組です。
+
例: "<Leader><S-j>,j"
+
+
+ -urls=urlpattern が与えられたとき、
+ そのマッピングは urlpattern で指定されたページのみで有効になります。
+
+
+
+ -
+ :fmapc
+ :fmapc! -modes=modes urlpattern
+
+
+ urlpattern のマッピングを削除します。
+ "!" が与えられたときは、全てのマッピングが削除されます。
+
+
+
+ -
+ :funmap
+ :funmap -urls=urlpattern -modes=modes lhs
+
+
+ マッピングを削除します。
+
+
+ urlpattern 付きのマッピングを削除するときは、-urls を指定する必要があります。
+
+
+
+ urlpattern
+
+ urlpattern の値は正規表現でなければいけません。
+
+ eventnamelist
+
+ eventnamelist は以下の値から構成されたリストです。
+
+
+ - keypress
+ - keydown
+ - keyup
+ - vkeypress
+ - vkeydown
+ - vkeyup
+
+ "v..." のものは、仮想キーコードでイベントを発行します。
+ キー毎に、書かれた順にイベントが発行されます。
+ このオプションのデフォルト値は "keypress" です。
+ xpath
+
+ キーイベントを送るべき要素を指定するための XPath。
+
+ framenumber
+
+ キーイベントを送るべきフレームの番号。
+ 番号は、補完を参考にしてください。
+
+ modes
+
+ マップするモードのリスト (デフォルトは、NORMALモード)
+
+ .vimperatorrc 用の fmaps サンプル
+ コマンドラインで直接に入力するときは、":lazy" を除いてください。
+
+:command! -nargs=+ lazy autocmd VimperatorEnter .* <args>
+:lazy fmaps -u='mail\.google\.com/mail' c / j k n p o u e x s r a # [ ] ? gi gs gt gd ga gc
+:lazy fmaps -u='mail\.google\.com/mail/.*/[0-9a-f]+$' c / j,n k,p n,j p,k o u e x s r a # [ ] ? gi gs gt gd ga gc
+:lazy fmaps -u='www\.google\.co\.jp/reader' -events=vkeypress j k n p m s v A r S N P X O gh ga gs gt gu u / ? J K
+:lazy fmaps -u='(fastladder|livedoor)\.com/reader' j k s a p o v c i,p <Space> <S-Space> z b < > q w e,g
+:lazy fmaps -u='https?://www\.rememberthemilk\.com/home/' j k m i c t ? d F,f G,g S,s L,l Y,y H,h M,m <Del> <C-S-Left> <C-S-Right>
+:lazy fmaps -u='http://code.google.com/p/vimperator-labs/issues/list' o j k
+:lazy fmaps -u='http://code.google.com/p/vimperator-labs/issues/detail' u
+
+`;
+
+// }}}
+
+(function () {
+
+ const EVENTS = 'keypress keydown keyup'.split(/\s+/);
+ const EVENTS_WITH_V = EVENTS.concat(['v' + n for each (n in EVENTS)]);
+ const IGNORE_URLS = //;
+
+ const VKeys = {
+ '0': KeyEvent.DOM_VK_0,
+ '1': KeyEvent.DOM_VK_1,
+ '2': KeyEvent.DOM_VK_2,
+ '3': KeyEvent.DOM_VK_3,
+ '4': KeyEvent.DOM_VK_4,
+ '5': KeyEvent.DOM_VK_5,
+ '6': KeyEvent.DOM_VK_6,
+ '7': KeyEvent.DOM_VK_7,
+ '8': KeyEvent.DOM_VK_8,
+ '9': KeyEvent.DOM_VK_9,
+ ';': KeyEvent.DOM_VK_SEMICOLON,
+ '=': KeyEvent.DOM_VK_EQUALS,
+ 'a': KeyEvent.DOM_VK_A,
+ 'b': KeyEvent.DOM_VK_B,
+ 'c': KeyEvent.DOM_VK_C,
+ 'd': KeyEvent.DOM_VK_D,
+ 'e': KeyEvent.DOM_VK_E,
+ 'f': KeyEvent.DOM_VK_F,
+ 'g': KeyEvent.DOM_VK_G,
+ 'h': KeyEvent.DOM_VK_H,
+ 'i': KeyEvent.DOM_VK_I,
+ 'j': KeyEvent.DOM_VK_J,
+ 'k': KeyEvent.DOM_VK_K,
+ 'l': KeyEvent.DOM_VK_L,
+ 'm': KeyEvent.DOM_VK_M,
+ 'n': KeyEvent.DOM_VK_N,
+ 'o': KeyEvent.DOM_VK_O,
+ 'p': KeyEvent.DOM_VK_P,
+ 'q': KeyEvent.DOM_VK_Q,
+ 'r': KeyEvent.DOM_VK_R,
+ 's': KeyEvent.DOM_VK_S,
+ 't': KeyEvent.DOM_VK_T,
+ 'u': KeyEvent.DOM_VK_U,
+ 'v': KeyEvent.DOM_VK_V,
+ 'w': KeyEvent.DOM_VK_W,
+ 'x': KeyEvent.DOM_VK_X,
+ 'y': KeyEvent.DOM_VK_Y,
+ 'z': KeyEvent.DOM_VK_Z,
+ '*': KeyEvent.DOM_VK_MULTIPLY,
+ '+': KeyEvent.DOM_VK_ADD,
+ '-': KeyEvent.DOM_VK_SUBTRACT,
+ ',': KeyEvent.DOM_VK_COMMA,
+ '.': KeyEvent.DOM_VK_PERIOD,
+ '/': KeyEvent.DOM_VK_SLASH,
+ '?': KeyEvent.DOM_VK_SLASH,
+ '`': KeyEvent.DOM_VK_BACK_QUOTE,
+ '{': KeyEvent.DOM_VK_OPEN_BRACKET,
+ '\\': KeyEvent.DOM_VK_BACK_SLASH,
+ '}': KeyEvent.DOM_VK_CLOSE_BRACKET,
+ '\'': KeyEvent.DOM_VK_QUOTE
+ };
+
+ const State = {
+ feeding: false
+ };
+
+ function id (v)
+ v;
+
+ function or (list, func)
+ (list.length && let ([head,] = list) (func(head) || or(list.slice(1), func)));
+
+ function getFrames () {
+ function bodyCheck (content)
+ (content.document && content.document.body && content.document.body.localName.toLowerCase() === 'body');
+
+ function get (content)
+ (bodyCheck(content) && result.push(content), Array.slice(content.frames).forEach(get));
+
+ let result = [];
+ get(content);
+ return result;
+ }
+
+ function fromXPath (doc, xpath) {
+ let result = util.evaluateXPath(xpath, doc);
+ return result.snapshotLength && result.snapshotItem(0);
+ }
+
+ function createEvent (eventName, event) {
+ let result = content.document.createEvent('KeyEvents');
+ result.initKeyEvent(
+ eventName,
+ true,
+ true,
+ content,
+ event.ctrlKey,
+ event.altKey,
+ event.shiftKey,
+ event.metaKey,
+ event.keyCode,
+ event.charCode
+ );
+ return result;
+ }
+
+ function virtualize (event) {
+ let cc = event.charCode;
+ if (/^[A-Z]$/.test(String.fromCharCode(cc)))
+ event.shiftKey = true;
+ event.keyCode = VKeys[String.fromCharCode(cc).toLowerCase()];
+ event.charCode = 0;
+ return event;
+ }
+
+ function feed (keys, eventNames, target) {
+ function finalize (){
+ modes.passAllKeys = _passAllKeys;
+ State.feeding = false;
+ }
+
+ State.feeding = true;
+
+ let _passAllKeys = modes.passAllKeys;
+
+ try {
+ modes.passAllKeys = true;
+ modes.passNextKey = false;
+
+ for (let [, keyEvent] in Iterator(events.fromString(keys))) {
+ eventNames.forEach(function (eventName) {
+ let ke = util.cloneObject(keyEvent);
+ let [, vkey, name] = eventName.match(/^(v)?(.+)$/);
+ if (vkey)
+ virtualize(ke);
+ let event = createEvent(name, ke);
+ target.dispatchEvent(event);
+ });
+ }
+ } catch (e) {
+ finalize();
+ throw e;
+ }
+
+ finalize();
+ }
+
+ function makeTryValidator (func)
+ function (value) {
+ try {
+ liberator.log(value);
+ func(value);
+ return true;
+ } catch (e) {}
+ return false;
+ };
+
+ let regexpValidator = makeTryValidator(RegExp);
+
+ let xpathValidator =
+ makeTryValidator(function (expr) document.evaluate(expr, document, null, null, null))
+
+ function fromModeString (s){
+ for (let [, {name, mask, char}] in Iterator(modes._modeMap))
+ if (s === name || s === char)
+ return mask;
+ }
+
+ function fromModeStrings (ss, def) {
+ if (def && (!ss || ss.length < 1))
+ return [modes.NORMAL];
+ return ss.map(fromModeString).filter(function (it) (typeof it === 'number'));
+ }
+
+ function modeStringsValidator (ss)
+ (!ss || (fromModeStrings(ss).length === ss.length));
+
+ function makeListValidator (list)
+ function (values)
+ (values && !values.some(function (value) !list.some(function (event) event === value)));
+
+ function findMappings ({all, filter, urls, ignoreUrls, not, result, modes: targetModes}) {
+ function match (map) {
+ let r = (
+ map.feedSomeKeys &&
+ (all ||
+ (!filter || filter === map.names[0]) &&
+ (ignoreUrls || urls === IGNORE_URLS || mappings._matchingUrlsTest(map, urls)))
+ );
+ if (result && r) {
+ if (typeof result.matched === 'number')
+ result.matched++;
+ else
+ result.matched = 1;
+ }
+ return !!r ^ !!not;
+ }
+
+ if (filter)
+ filter = mappings._expandLeader(filter);
+ if (urls)
+ urls = RegExp(urls);
+
+ // FIXME 同じオブジェクトがダブって返るかも(あるいはそれで良い?)
+ let result = [];
+ for (let [, m] in Iterator(targetModes || [modes.NORMAL]))
+ result = result.concat(mappings._user[m].filter(match));
+
+ return result;
+ }
+
+ function unmap (condition) {
+ condition = Object.create(condition);
+ let ms = condition.modes || [modes.NORMAL];
+ condition.not = true;
+ condition.modes = undefined;
+ for (let [, m] in Iterator(ms)) {
+ condition.modes = [m];
+ mappings._user[m] = findMappings(condition);
+ }
+ }
+
+ function list (condition) {
+ let maps = findMappings(condition);
+ let template = modules.template;
+ let length = 0;
+ let list =
+ xml`
+ ${
+ template.map(maps, function (map){
+ ++length;
+ return template.map(map.names, function (name)
+ xml`
+ ${name} |
+ ${map.feedSomeKeys.rhs} |
+ ${map.matchingUrls ? map.matchingUrls : '[Global]'} |
+
`)
+ })
+ }
+
`;
+
+ if (length == 0) {
+ liberator.echomsg("No mapping found");
+ return;
+ }
+ commandline.echo(list, commandline.HL_NORMAL, commandline.FORCE_MULTILINE);
+ }
+
+ function fmapCompleter (context, args) {
+ context.title = ['name', 'rhs & url'];
+ context.completions = [
+ [
+ xml`${map.names[0]},
+
+ ${map.feedSomeKeys.rhs}
+ ${
+ args['-ignoreurls']
+ ? xml` for ${map.matchingUrls ? map.matchingUrls : 'Global'}`
+ : ''
+ }
+ `
+ ]
+ for each (map in findMappings({urls: args['-urls'], ignoreUrls: args['-ignoreurls']}))
+ ];
+ }
+
+ function urlCompleter ({currentURL}) {
+ return function (context, args) {
+ let maps = findMappings({all: true});
+ let uniq = {};
+ let result = [
+ (uniq[map.matchingUrls] = 1, [map.matchingUrls.source, map.names])
+ for each (map in maps)
+ if (map.matchingUrls && !uniq[map.matchingUrls])
+ ];
+ if (currentURL) {
+ result.unshift(['^' + util.escapeRegex(buffer.URL), 'Current URL']);
+ if (content.document.domain)
+ result.unshift([util.escapeRegex(content.document.domain), 'Current domain']);
+ }
+ return result;
+ };
+ }
+
+ function frameCompleter (context, args) {
+ return [
+ [i, frame.document.location]
+ for each ([i, frame] in Iterator(getFrames()))
+ ];
+ }
+
+ const ModeStringsCompleter = [
+ [name, disp + ' mode' + (char ? ' (alias: ' + char + ')' : '')]
+ for ([n, {name, char, disp, extended}] in Iterator(modes._modeMap))
+ if (!extended && /^\D+$/.test(n))
+ ];
+
+
+ 'fmap fmaps'.split(/\s+/).forEach(function (cmd) {
+ let multi = cmd === 'fmaps';
+
+ function action (multi) {
+ return function (args) {
+ let prefix = args['-prefix'] || '';
+ let ms = fromModeStrings(args['-modes'], true);
+
+ function add ([lhs, rhs]) {
+ if (!lhs)
+ return;
+
+ rhs = rhs || lhs;
+ mappings.addUserMap(
+ ms,
+ [prefix + lhs],
+ args['description'] || 'by feedSomeKeys_3.js',
+ function () {
+ function body (win)
+ (win.document.body || win.document);
+
+ let win = document.commandDispatcher.focusedWindow;
+ let frames = getFrames();
+
+ let elem = liberator.focus || body(win);
+
+ if (typeof args['-frame'] !== 'undefined') {
+ frames = [frames[args['-frame']]];
+ elem = body(frames[0]);
+ }
+
+ if (args['-xpath']) {
+ elem = or(frames, function (f) fromXPath(f.document, args['-xpath'])) || elem;
+ }
+
+ if (args['-selector']) {
+ elem = or(frames, function (f) f.document.querySelector(args['-selector'])) || elem;
+ }
+
+ feed(rhs, args['-events'] || ['keypress'], elem);
+ },
+ {
+ matchingUrls: args['-urls'],
+ feedSomeKeys: {
+ rhs: rhs,
+ }
+ },
+ true
+ );
+ }
+
+ if (multi) {
+ let sep = let (s = args['-separator'] || ',') function (v) v.split(s);
+ args.literalArg.split(/\s+/).map(String.trim).map(sep).forEach(add);
+ } else {
+ let [, lhs, rhs] = args.literalArg.match(/^(\S+)\s+(.*)$/) || args.literalArg;
+ if (!rhs) {
+ list({
+ filter: prefix + args.literalArg.trim(),
+ urls: args['-urls'],
+ ignoreUrls: !args['-urls'],
+ modes: ms
+ });
+ } else {
+ add([lhs, rhs]);
+ }
+ }
+ };
+ }
+
+ commands.addUserCommand(
+ [cmd],
+ 'Feed map a key sequence',
+ action(multi),
+ {
+ literal: 0,
+ options: [
+ [['-modes', '-m'], commands.OPTION_LIST, modeStringsValidator, ModeStringsCompleter],
+ [['-urls', '-u'], commands.OPTION_STRING, regexpValidator, urlCompleter({currentURL: true})],
+ [['-desc', '-description', '-d'], commands.OPTION_STRING],
+ [['-frame', '-f'], commands.OPTION_INT, null, frameCompleter],
+ [['-xpath', '-x'], commands.OPTION_STRING, xpathValidator],
+ [['-selector', '-s'], commands.OPTION_STRING],
+ [['-prefix', '-p'], commands.OPTION_STRING],
+ [
+ ['-events', '-e'],
+ commands.OPTION_LIST,
+ makeListValidator(EVENTS_WITH_V),
+ EVENTS_WITH_V.map(function (v) [v, v])
+ ]
+ ].concat(
+ multi ? [[['-separator', '-s'], commands.OPTION_STRING]]
+ : []
+ ),
+ completer: multi ? null : fmapCompleter
+ },
+ true
+ );
+ });
+
+ commands.addUserCommand(
+ ['fmapc'],
+ 'Clear fmappings',
+ function (args) {
+ let ms = fromModeStrings(args['-modes'], true);
+ if (args.bang) {
+ unmap({ignoreUrls: true, modes: ms});
+ liberator.log('All fmappings were removed.');
+ } else {
+ let result = {};
+ unmap({urls: args.literalArg, result: result, modes: ms});
+ liberator.echo(result.matched ? 'Some fmappings were removed.' : 'Not found specifed fmappings.');
+ }
+ },
+ {
+ literal: 0,
+ bang: true,
+ completer: function (context) {
+ context.title = ['URL Pattern'];
+ context.completions = urlCompleter({})(context);
+ },
+ options: [
+ [['-modes', '-m'], commands.OPTION_LIST],
+ ]
+ },
+ true
+ );
+
+ commands.addUserCommand(
+ ['funmap'],
+ 'Remove fmappings',
+ function (args) {
+ let urls = args['-urls'];
+ let name = args.literalArg;
+ if (!name)
+ return liberator.echoerr('E471: Argument required');
+
+ let result = {};
+ unmap({
+ filter: name,
+ urls: urls,
+ ignoreUrls: args['-ignoreurls'],
+ result: result,
+ modes: fromModeStrings(args['-modes'], true)
+ });
+ liberator.echo(result.matched ? 'Some fmappings were removed.' : 'Not found specifed fmappings.');
+ },
+ {
+ literal: 0,
+ options: [
+ [['-modes', '-m'], commands.OPTION_LIST],
+ [['-urls', '-u'], commands.OPTION_STRING, regexpValidator, urlCompleter({})],
+ [['-ignoreurls', '-iu'], commands.OPTION_NOARG]
+ ],
+ completer: fmapCompleter
+ },
+ true
+ );
+
+ plugins.libly.$U.around(
+ mappings,
+ 'getCandidates',
+ function (next, [mode, prefix, patternOrUrl]) {
+ let map = mappings.get(mode, prefix, patternOrUrl);
+ if (map && map.matchingUrls)
+ return [];
+ return next();
+ }
+ );
+
+ __context__.API =
+ 'State VKeys feed getFrames fromXPath virtualize unmap findMappings list'.split(/\s+/).reduce(
+ function (result, name)
+ (result[name] = eval(name), result),
+ {}
+ );
+
+})();
+
+// vim:sw=2 ts=2 et si fdm=marker:
diff --git a/vimperator/plugin/wallabag.js b/vimperator/plugin/wallabag.js
new file mode 100644
index 0000000..363677b
--- /dev/null
+++ b/vimperator/plugin/wallabag.js
@@ -0,0 +1,35 @@
+let PLUGIN_INFO = xml`
+
+ wallabag
+ Pocket
+ 0.1.1
+ 3.2
+ Philipp Schmitt
+ https://raw.github.com/pschmitt/vimperator-wallabag/master/wallabag.js
+
+`;
+
+(function() {
+
+ let wallabag_url = (liberator.globalVariables.wallabag_url) ? liberator.globalVariables.wallabag_url : '';
+
+ commands.addUserCommand(['wallabag', 'wg'], 'Wallabag plugin',
+ function(args) {
+ let url = buffer.URL;
+
+ if (typeof args != 'undefined' && args.length > 0) {
+ url = args;
+ }
+
+ if (wallabag_url == '') {
+ liberator.echoerr('Wallabag URL undefined. Please add let g:wallabag_url="http://YOURURL" to your vimperatorrc');
+ } else {
+ liberator.open(wallabag_url + '/?action=add&url=' + btoa(url), liberator.NEW_TAB);
+ }
+ }
+ );
+
+
+})();
diff --git a/vimperatorrc b/vimperatorrc
new file mode 100644
index 0000000..09e95b8
--- /dev/null
+++ b/vimperatorrc
@@ -0,0 +1,50 @@
+set runtimepath=~/etc/vimperator
+
+set gui=none,tabs
+"set tabnumbers
+
+set defsearch=g
+
+" follow hints on return
+set followhints=1
+
+set incsearch hlsearch
+set ignorecase smartcase
+
+set noerrorbells novisualbell
+js liberator.beep = function() { return false; }
+
+" google
+map s og
+map S tg
+
+" fast scrolling
+noremap j
+noremap k
+
+let g:wallabag_url="https://wllbg.gebner.org"
+
+js <
diff --git a/vimrc b/vimrc
index d881929..7756e1b 100644
--- a/vimrc
+++ b/vimrc
@@ -59,6 +59,7 @@ NeoBundle 'derekwyatt/vim-scala'
NeoBundle 'othree/html5.vim'
NeoBundle 'dogrover/vim-pentadactyl'
+NeoBundle 'superbrothers/vim-vimperator'
NeoBundle 'idris-hackers/idris-vim'