しまてく

学んだ技術を書きためるブログ

vimperator用のdeliciousのBookmarkをインクリメンタルサーチできるプラグイン書いた!ver2

これはなに?

基本的に以前書いたものの改良版です。

出来ることはソーシャルブックマークサービスのdelicious.comから
インクリメンタルでブックマークを検索です。

検索のヒット対象は、「タグ」「URL」「ブックマーク名」の3つです。

使い方はvimperatorのコマンドで「:delicious 」と入れたあとに
検索したいキーワードを入力していくだけという親切設計!

細かく動きを設定したい人は、vimperatorrc に以下の設定を書くことで動作を指定できます。

g:delicious_serch_serch_type
検索時にOR検索をするかAND検索をするか。
設定値:"or" もしくは "and"
初期値:"and"

g:delicious_serch_serch_target
検索時にどこから検索するか。
設定値:
"u": urlから検索
"d": description(deliciousに登録する際に入力する説明文)から検索
"t": tagから検索
上記設定値は同時指定可。
初期値:"udt"

ということで

vimperator × delicious な人は是非使ってみてください><
使えねーぞゴルァ等のコメントでもいいのでフィードバックもらえると喜びます><><

ソース

// Vimperator plugin: 'IncSearch in del.icio.us Bookmarks'
// Last Change: 04-Oct-2008.
// License: MIT
// Maintainer: cimadai <dice.k1984@gmail.com> - http://d.hatena.ne.jp/cimadai
//
// del.icio.us のブックマークの[URL][タグ][htmlのタイトル]から検索
//
// 説明://{{{
// 初回使用時にブックマークを取得します。
// ブラウジング中に登録したブックマークを検索したい場合は「:deliciousload」で再読み込みをしてください。
// delicious APIの全件取得がよく失敗します。その場合は自動で直近100件の取得を行います。
// インクリメンタルサーチは初期設定ではAND検索です。
////}}}
// 設定://{{{
// vimperatorrc で以下のパラメーターを指定できます。
//
// g:delicious_serch_serch_type
//  検索時にOR検索をするかAND検索をするか。
//  設定値:"or" もしくは "and"
//  初期値:"and"
//
// g:delicious_serch_serch_target
//  検索時にどこから検索するか。
//  設定値:
//      "u": urlから検索
//      "d": description(deliciousに登録する際に入力する説明文)から検索
//      "t": tagから検索
//      上記設定値は同時指定可。
//  初期値:"udt"
//}}}

(function(){
    const allEndPoint = "https://api.del.icio.us/v1/posts/all?"
    const recentEndPoint = "https://api.del.icio.us/v1/posts/recent?"

    var deli_bookmarks = [];
    var targetParam = {
        "u": "href",
        "d": "description",
        "t": "tag"
    };

    // _loadDeliciousBookmark (xhrを使って裏でブックマーク取得)//{{{
    function _loadDeliciousBookmark(){
        deli_bookmarks = [];
        var xhr = new XMLHttpRequest();

        // まず全件取得を試みる//{{{
        if( deli_bookmarks.length == 0 ){
            xhr.open("GET", allEndPoint, false);
            xhr.send(null);

            var match = xhr.responseText.match(/<post .*?>/g);
            if( match ) match.forEach( function(post){
                var deli_bookmark = {};
                post.match(/href="(.*?)"|description="(.*?)"|tag="(.*?)"/g).forEach( function(r){
                    var w = r.split("=");
                    deli_bookmark[ w[0] ] = w[1].replace(/^"|"$/g,"");
                });
                deli_bookmarks.push( deli_bookmark );
            });

            if( deli_bookmarks.length > 0 ){
                liberator.echo( deli_bookmarks.length + ' bookmarks loaded!(all bookmarks)' );
                return true;
            }
        }//}}}

        // 全件取得のAPIで失敗した場合は、直近の100件を取得//{{{
        if( deli_bookmarks.length == 0 ){
            xhr.open("GET",recentEndPoint + "&count=" + 100, false);
            xhr.send(null);

            var match = xhr.responseText.match(/<post .*?>/g);
            if( match ) match.forEach( function(post){
                var deli_bookmark = {};
                post.match(/href="(.*?)"|description="(.*?)"|tag="(.*?)"/g).forEach( function(r){
                    var w = r.split("=");
                    deli_bookmark[ w[0] ] = w[1].replace(/^"|"$/g,"");
                });
                deli_bookmarks.push( deli_bookmark );
            });

            if( deli_bookmarks.length > 0 ){
                liberator.echo( deli_bookmarks.length + ' bookmarks loaded!(recently bookmarks)' );
                return true;
            }
        }//}}}

        // 取得できなかった
        return false;
    }//}}}

    // IncSearch :delicious keyword//{{{
    liberator.commands.addUserCommand(['delicious'], "IncSearch in delicious",
        function(arg){
            var url = arg.replace(/ \[.*?\ ]/, "");
            if(url) liberator.open(url, liberator.NEW_TAB);
        },
        {
            completer: function (filter) {//{{{
                // bookmarkが読み込まれていなければ読み込み
                if( deli_bookmarks.length == 0 ) _loadDeliciousBookmark();
                var serchType = liberator.globalVariables.delicious_serch_serch_type || 'and';
                var serchTarget = liberator.globalVariables.delicious_serch_serch_target || 'udt';

                var completionHash = {}; // 補完リスト
                deli_bookmarks.forEach(function(r){
                    var filters = filter.split(/\s/); // 半角スペース区切りで検索
                    var targets = serchTarget.split(/\s*/); // 一文字単位にsplitする
                    var isHit = (serchType == "and") ? true : false;

                    if( filters ) filters.forEach( function(f){
                        if( f == "" ) return;
                        var regobj = new RegExp(".*" + f + ".*", "i");

                        if( serchType == "and"){
                            targets.forEach(function(t){
                                if( targetParam[t] ) isHit = isHit && !regobj.test(r[targetParam[t]]);
                            });
                            isHit = !isHit;
                        }
                        else{
                            targets.forEach(function(t){
                                if( targetParam[t] ) isHit = isHit || regobj.test(r[targetParam[t]]);
                            });
                        }
                    });

                    if( isHit ) completionHash[r.href] = [ r.href + " [ " + r.description + " ]", r.tag];
                });

                var completionList = [];
                for (var key in completionHash) {
                    completionList.push(completionHash[key]);
                }
                return [0,completionList];
           }//}}}
        }
    );//}}}

    // TagReload :deliciousload (強制的に再読み込み、新しくブックマーク追加したときに呼ぶ)//{{{
    liberator.commands.addUserCommand(['deliciousload', 'dell'], "reload del.icio.us Bookmarks",
        function(arg){
            if( !_loadDeliciousBookmark() ){
                liberator.echoerr("sorry... bookmarks load faild.");
            }
        },{ }
    );//}}}
})();

// vim:sw=4 ts=4 foldmethod=marker et: