var PLUGIN_INFO = {NAME} Hatena Bookmark UserSearch はてなブックマークユーザ検索 2.0pre 2.0pre https://github.com/vimpr/vimperator-plugins/raw/master/hatena-bookmark-search.js Yuichi Tateno MPL 1.1/GPL 2.0/LGPL 2.1 1.0.2 || :bs[earch][!] word :tabbs[earch][!] word ||< ログインしているユーザのブックマークを、URL, コメント, タイトル から検索します。 はてなブックマークユーザページの右上の検索のローカル版のようなイメージです。 XUL/Migemo が入っている場合は Migemo を使い正規表現検索します。 Migemo を利用した検索語の絞り込みはスペース区切りの 2単語までとなります。 Migemo を利用すると検索が重くなるので、遅いマシンやインクリメンタル検索環境下では、以下の設定をすることで migemo 検索をしなくなります。 >|| let g:hatena_bookmark_no_migemo='true'; ||< また >|| let g:hatena_bookmark_suffix_array='true'; ||< とすることで、SuffixArray での検索を有効にします。現在は SuffixArray の構築に時間がかかるため、10000件ぐらいまでのブックマークでないと実用的ではありません。SuffixArray を利用すると、検索のコストが10000件ぐらいでは 1,2ms ぐらいになるとおもいます。また migemo 検索はできません。 :bs word では、選択している URL を開きます。:bs! word では、選択している URL のはてなブックマークエントリーページを開きます。:bs と単語を入力しないと、http://b.hatena.ne.jp/my を開きます。:bs! では http://b.hatena.ne.jp/ トップページを開きます。 初回検索時にデータを構築しますが、強制的にデータをロードし直したい時などは >|| :bs -reload ||< としてください。 (invalid options エラーが出る場合は、適当な文字を後ろに付加するか、最新(Nightly)の Vimperator を使ってください) また、:open, :tabopen の補完で、completeオプションに "H" を追加することではてなブックマークの検索が可能です。 >|| :set complete+=H ||< .vimperatorrcに書く場合は >|| autocmd VimperatorEnter .* :set complete+=H ||< としてください。 == ChangeLog == - 1.0.2 -- ヌル文字を消す - 1.0.1 -- ドキュメントの追加 - 1.0.0 -- キャッシュの追加, SuffixArray 検索の追加 ]]> ; liberator.plugins.HatenaBookmark = (function(){ let p = function(arg) { Application.console.log(''+arg); // liberator.log(arg); } p.b = function(func, name) { let now = (new Date() * 1); func(); let t = (new Date() * 1) - now; // p('sary: ' + name + ': ' + t); } const HatenaBookmark = {}; HatenaBookmark.Data = new Struct('data'); /* * title * comment * url */ HatenaBookmark.Data.prototype.__defineGetter__('title', function() this.data.split("\n")[0].replace("\0", '')); HatenaBookmark.Data.prototype.__defineGetter__('comment', function() this.data.split("\n")[1]); HatenaBookmark.Data.prototype.__defineGetter__('url', function() this.data.split("\n")[2]); HatenaBookmark.Data.prototype.__defineGetter__('icon', function() bookmarks.getFavicon(this.url)); HatenaBookmark.Data.prototype.__defineGetter__("extra", function () [ ["comment", this.comment, "Comment"], ].filter(function (item) item[1])); var XMigemoCore; var XMigemoTextUtils; try { XMigemoCore = Cc['@piro.sakura.ne.jp/xmigemo/factory;1'] .getService(Ci.pIXMigemoFactory) .getService("ja"); XMigemoTextUtils = Cc['@piro.sakura.ne.jp/xmigemo/text-utility;1'].getService(Ci.pIXMigemoTextUtils); } catch (e if e instanceof TypeError) { } HatenaBookmark.useSuffixArray = !!(liberator.globalVariables.hatena_bookmark_suffix_array); HatenaBookmark.useMigemo = !!(!liberator.globalVariables.hatena_bookmark_no_migemo && XMigemoCore); HatenaBookmark.reload = function() { if (HatenaBookmark.useSuffixArray) { HatenaBookmark.SuffixArray.reload(); } else { HatenaBookmark.UserData.reload(); } } HatenaBookmark.Command = { templateDescription: function (item, text) { return <> { !(item.extra && item.extra.length) ? "" : { template.map(item.extra, function (e) <>{e[1]}, <> /* Non-breaking space */) } } }, templateTitleIcon: function (item, text) { var simpleURL = text.replace(/^https?:\/\//, ''); if (simpleURL.indexOf('/') == simpleURL.length-1) simpleURL = simpleURL.replace('/', ''); return <>{item.icon ? : <>}{item.item.title} { simpleURL } }, filter: function (_item) { var item = _item.item; // 'this' is context object. if (HatenaBookmark.useMigemo) { if (!this.migemo) { this.migemo = HatenaBookmark.Command.compileRegexp(this.filter); } var migemo = this.migemo; return migemo.test(item.data); } else { return this.match(item.url) || this.match(item.comment) || this.match(item.title); } }, compileRegexp: function(str) { let a; with (XMigemoTextUtils) { a = sanitize(trim(str)).split(/\s+/).join(' '); } return new RegExp(XMigemoTextUtils.getANDFindRegExpFromTerms(XMigemoCore.getRegExps(a)), 'gim'); }, execute: function(args) { if (args['-reload']) { HatenaBookmark.reload(); liberator.echo('HatenaBookmark data reloaded.'); return; } var url = HatenaBookmark.Command.genURL(args); liberator.open(url); }, executeTab: function(args)
var PLUGIN_INFO =
<VimperatorPlugin>
<name>{NAME}</name>
<description>History search backward like UNIX shell.</description>
<description lang="ja">UNIX シェルのようなC-rで履歴検索を行うプラグイン</description>
<minVersion>2.0</minVersion>
<maxVersion>2.0</maxVersion>
<updateURL>http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/history-search-backward.js</updateURL>
<author mail="hotchpotch@gmail.com" homepage="http://d.hatena.ne.jp/secondlife/">Yuichi Tateno</author>
<license>MIT</license>
<version>0.2</version>
<detail><![CDATA[
UNIX シェルのようにコマンドラインで C-r でヒストリ検索を行うプラグインですmap の変更設定は以下のように行えます
>||
liberator.globalVariables.history_search_backward_map = ['<C-r>'];
||<

]]></detail>
</VimperatorPlugin>;

(function() {
    let p = function(msg) {
        Application.console.log(''+msg);
    }

    let evalWithContext = function(func, context) {
        let str;
        let fstr = func.toString();
        if (fstr.indexOf('function () {') == 0) {
            str = fstr.replace(/.*?{([\s\S]+)}.*?/m, "$1");
        } else {
            str = '(' + fstr + ')()';
        }
        return liberator.eval(str, context);
    }

    let showCompletions = function() {
        if (!options.get('wildoptions').has('auto')) {
            evalWithContext(function() {
                completions.complete(true, false);
                completions.itemList.show();
            }, commandline.input);
        }
    }

    let next = function() {
        evalWithContext(function() completions.tab(false), commandline.input);
    }

    let prev = function() {
        evalWithContext(function() completions.tab(true), commandline.input);
    }

    const commandlineWidget = document.getElementById("liberator-commandline");

    mappings.addUserMap([modes.COMMAND_LINE], 
        liberator.globalVariables.history_search_backward_map || ['<C-r>'], 
        'History incremental search backward.', 
        function() 
        {
            if (evalWithContext(function() completions.itemList.visible(), commandline.input)) {
                next();
                return;
            }

            let command = commandline.command || '';
            let completionsList = [[key, i] for ([i, key] in storage['history-command'])].
                                      filter(function([key, i]) key).reverse();

            commandline.input('bck-i-search: ', function(str) {
                try {
                    liberator.execute(str);
                } catch(e) {};
                modes.pop();
                return;
            }, {
                completer: function(context) {
                    context.title = ['CommandLine History', 'INDEX'];
                    context.completions = completionsList;
                },
                onChange: function() {
                    showCompletions();
                },
                default: command,
            });
            showCompletions();
        }
    );
})();