ブックマークをタグで絞りこんで開く
TagSifterは、高機能だけど結局絞り込みしか使ってないし、サイドバー開くことが面倒になってきた…orz
でも :bmarks が 使い辛かったので、作ってみた。
- completion で タグとそのタグで含まれる ブックマークを表示される
- 絞り込んで結果に対して
- 指定無しなら全て開く
- 番号を記載でその番号のブックマークを開く
- 複数ある場合は、コンマ区切り
- 1,2,3,4と 1-4 は 等価
- 0,1,2,3,4 と -4 は 等価
- 4,5,6,7,... と 4- は 等価
- 1,2,3,7 と 1-3,7 は 等価
- 毎回全検やってるので、遅いorz
作ってて思ったけど、今は、オンラインブックマークのほうが多いのかなぁ
(function(){ let mod=liberator.modules; let cmd=mod.commands; let n_style="display:inline-block;color:#20c;width:1em;text-align:right;font-weight:bold"; let process=[ function(item,text){ return <> <span style={n_style}>{item.item.index}</span> <span highlight="CompIcon">{item.icon ? <img src={item.icon}/> : <></>}</span> <span class="td-strut"/>{item.item.url ? item.item.desc : text}</>; },function(item,text){ return <> {item.item.url ? <a highlight="URL" href={item.item.url}>{item.item.url}</a> : <span>{text}</span>} </>; } ]; let openURL = function(url){ liberator.open(url, liberator.NEW_TAB); }; let openURLs = ("TreeStyleTabService" in window) ? function(list){ TreeStyleTabService.readyToOpenNewTabGroup(gBrowser); gBrowser.loadTabs(["about:blank"].concat(list)); }:function(list){ for(let url in mod.util.Array.itervalues(list)) liberator.open(url, liberator.NEW_BACKGROUND_TAB); }; var Check=function(){ this.rule=[]; } Check.prototype={ addRule:function(msg){ let m=msg.match(/^(\d+)?(-)?(\d+)?$/); if(m[1]){ if(m[2]){ if(m[3]) this.addMinMax(m[1],m[3]); else this.addMin(m[1]); }else this.addIndex(m[1]); }else if(m[3]) this.addMax(m[3]); } ,addIndex: function(v){this.rule.push(function(idx) idx==v);} ,addMin:function(v){this.rule.push(function(idx) idx>=v);} ,addMax:function(v){this.rule.push(function(idx) idx<=v);} ,addMinMax:function(v,w){this.rule.push(function(idx)(v<=idx)&&(idx<=w));} ,check:function(idx){ for(var func in mod.util.Array.itervalues(this.rule)) if(func(idx)) return true; return false; } }; var map ={ modes:[liberator.modules.modes.NORMAL] ,keys:["<C-t>"] ,desc:"open bookmark from tag" ,action:function open_cmd(){ commandline.open("",":tagopen /",liberator.modules.modes.EX); } }; mappings.addUserMap(map.modes,map.keys, map.desc, map.action); cmd.addUserCommand(["tagopen"],"open bookmark from tag" ,function(args){ let tags=args[0].match(/([^/]+)/g); if(!tags){ liberator.echoerr("no tag list!"); return; } let c = new Check(); let all=true,m,cnt=0; let lastTag=tags[tags.length-1]; if(/^[0-9-,]+$/.test(lastTag)){ tags=tags.slice(0,-1); for(let r in mod.util.Array.itervalues(lastTag.split(","))){ c.addRule(r); } all = false; } var list=[ u.url for(u in mod.util.Array.itervalues(bookmarks.get("",tags))) if(all || c.check(cnt++))]; if(list.length === 0) liberator.echoerr("no match bookmark"); else if(list.length === 1) openURL(list[0]); else openURLs(list); },{ argCount: "1" ,completer:function(context,args){ let ex; try{ let q=context.filter.split("/"); context.title = ["tag","description"]; if(q.length <3){ let p=[]; let tags=PlacesUtils.tagging.allTags; for(let i=0,j=tags.length;i<j;++i){ p.push(["/"+tags[i],i]); } context.completions=p; }else{ q=q.slice(1,-1); let tags={}; result=bookmarks.get("",q); let bm=[]; let path="/"+q.join("/")+"/"; let cnt=0; for(let r in mod.util.Array.itervalues(result)){ let t=r.tags; for(let t1 in mod.util.Array.itervalues(t)){ if(tags[t1]) ++tags[t1]; else tags[t1] = 1; } bm.push({text:path+cnt,desc:r.title||"(Untitled)",ico:r.icon,index:cnt++,url:r.url}); } for(let a in mod.util.Array.itervalues(q)) delete tags[a]; context.process = process; context.keys={ text:"text",description:"desc",icon:"ico" }; context.completions=[{text:path,desc:"current path",index:""}] .concat([ {text:path+a,desc:b,index:""} for([a,b] in Iterator(tags))] ,bm); } }catch(ex){ liberator.echoerr(ex); } } }); })(); </div> さて次はどの アドオン を ダイエットしようかなっと *1241001667*[javascript][vimperator]tree style tab を キーボード操作 概ねフィーリング通り動いたんで貼り ** 追記 いきなり 間違い発見して訂正orz やっぱり、git とか hg で 管理しないと面倒かも… <div class="code"> >|javascript| (function(){ if(!"TreeStyleTabService" in window) return; var mod=liberator.modules; var map=mod.mappings; var extra={flags:mod.Mappings.flags.COUNT}; let caisui; var setup=function(k,t,f){ map.remove(k,t); map.addUserMap([mod.modes.NORMAL],[k],t,function(){caisui.TreeStyleTab[f].apply(this,arguments)},extra); }; setup("zn" , "tree style tab next parent tab" , "nextParentTab"); setup("zN" , "tree style tab next root tab" , "nextRootTab"); setup("zj" , "tree style tab next tab" , "nextTab"); setup("zp" , "tree style tab prev parent tab" , "prevParentTab"); setup("zP" , "tree style tab prev root tab" , "prevRootTab"); setup("zk" , "tree style tab prev tab" , "prevTab"); setup("zd" , "remove tree tab" , "removeTabSubTree"); setup("zD" , "remove tree tab from top tree" , "removeTabTreeAll"); setup("zh" , "tree style tab parent tab" , "parentTab"); setup("zH" , "tree style tab root tab" , "rootTab"); setup("zl" , "tree style tab first child tab" , "firstChildTab"); setup("zu" , "move up" , "moveUp"); setup("zU" , "move root" , "moveRoot"); setup("d" , "override remove tab" , "removeTab"); setup("zc" , "collapse subtree" , "collapseSubtree"); setup("zC" , "collapse all subtree" , "collapseAllSubtree"); setup("zo" , "expand subtree" , "expandSubtree"); setup("z^" , "goto first tab" , "firstTab"); setup("z$" , "goto last tab" , "lastTab"); setup("z@" , "ready to open child tab once" , "readyToOpenChildTabOnce"); setup("z'" , "ready to open child tab once" , "readyToOpenTabOnce"); setup("z[" , "ready to open child tab" , "readyToOpenChildTab"); setup("z]" , "stop to open child tab" , "stopToOpenChildTab"); setup("zg" , "show tabbar" , "showTabbar"); setup("zx" , "mark tab" , "setMarkTab"); setup("zv" , "move child tab" , "moveChildTab"); setup("zV" , "show next tab" , "moveNextTab"); if(!liberator.plugins.caisui) liberator.plugins.caisui={}; liberator.plugins.caisui.TreeStyleTab={ getNextTab:function(aTab, aCount){ let t1; if(aCount < 1) aCount=1; for(t1=aTab,i=0; (i<aCount);++i){ let t2=TreeStyleTabService.getNextSiblingTab(t1); if(t2) t1=t2; else{ t1 = (t2=TreeStyleTabService.getParentTab(t1)) ? TreeStyleTabService.getFirstChildTab(t2) : TreeStyleTabService.getFirstTab(gBrowser); } } return t1; },nextTab:function(aCount){ gBrowser.selectedTab = caisui.TreeStyleTab.getNextTab(gBrowser.selectedTab,aCount); },nextParentTab:function(aCount){ var t=gBrowser.selectedTab; gBrowser.selectedTab = caisui.TreeStyleTab.getNextTab( TreeStyleTabService.getParentTab(t) || TreeStyleTabService.getRootTab(t) ,aCount); },nextRootTab:function(aCount){ gBrowser.selectedTab = caisui.TreeStyleTab.getNextTab(TreeStyleTabService.getRootTab(gBrowser.selectedTab),aCount); },getPrevTab:function(aTab,aCount){ let t1; if(aCount < 1) aCount=1; for(t1=aTab,i=0; (i<aCount);++i){ let t2=TreeStyleTabService.getPreviousSiblingTab(t1); if(t2) t1=t2; else{ t1 = (t2=TreeStyleTabService.getParentTab(t1)) ? TreeStyleTabService.getLastChildTab(t2) : TreeStyleTabService.getRootTab(TreeStyleTabService.getLastTab(gBrowser)); } } return t1; },prevTab:function(aCount){ gBrowser.selectedTab = caisui.TreeStyleTab.getPrevTab(gBrowser.selectedTab,aCount); },prevParentTab:function(aCount){ var t=gBrowser.selectedTab; gBrowser.selectedTab = caisui.TreeStyleTab.getPrevTab( TreeStyleTabService.getParentTab(t)||TreeStyleTabService.getRootTab(t) ,aCount); },prevRootTab:function(aCount){ gBrowser.selectedTab = caisui.TreeStyleTab.getPrevTab(TreeStyleTabService.getRootTab(gBrowser.selectedTab),aCount); },removeTab:function(){ var t=gBrowser.selectedTab; if(!TreeStyleTabService.getNextSiblingTab(t) && !TreeStyleTabService.hasChildTabs(t)){ p = TreeStyleTabService.getPreviousSiblingTab(t)||TreeStyleTabService.getParentTab(t); if(p) gBrowser.selectedTab = p; } gBrowser.removeTab(t); },parentTab:function(){ var t = TreeStyleTabService.getParentTab(gBrowser.selectedTab); if(t) gBrowser.selectedTab=t; },rootTab:function(){ gBrowser.selectedTab = TreeStyleTabService.getRootTab(gBrowser.selectedTab); },firstChildTab:function(){ var t = TreeStyleTabService.getFirstChildTab(gBrowser.selectedTab); if(t) gBrowser.selectedTab=t; },removeTabSubTree:function(){ caisui.TreeStyleTab.collapseSubtree.apply(this,arguments); gBrowser.removeTab(gBrowser.selectedTab); },removeTabTreeAll:function(){ gBrowser.selectedTab = TreeStyleTabService.getRootTab(gBrowser.selectedTab); caisui.TreeStyleTab.removeTabSubTree.apply(this,arguments); },collapseSubtree:function(){ gBrowser.treeStyleTab.collapseExpandSubtree(gBrowser.selectedTab,true); },expandSubtree:function(){ gBrowser.treeStyleTab.collapseExpandSubtree(gBrowser.selectedTab,false); },collapseAllSubtree:function(){ TreeStyleTabService.collapseExpandAllSubtree(true); },firstTab:function(){ let t1,t2; t1=gBrowser.selectedTab; gBrowser.selectedTab = (t2=TreeStyleTabService.getParentTab(t1)) ? TreeStyleTabService.getFirstChildTab(t2) : TreeStyleTabService.getFirstTab(gBrowser); },lastTab:function(){ let t1,t2; t1=gBrowser.selectedTab; gBrowser.selectedTab = (t2=TreeStyleTabService.getParentTab(t1)) ? TreeStyleTabService.getLastChildTab(t2) : TreeStyleTabService.getRootTab(TreeStyleTabService.getLastTab(gBrowser)); },readyToOpenChildTabCore:function(aTab,aFlag){ TreeStyleTabService.readyToOpenChildTab(aTab,aFlag); },readyToOpenChildTabOnce:function(){ caisui.TreeStyleTab.readyToOpenChildTabCore(gBrowser.selectedTab); },readyToOpenTabOnce:function(){ caisui.TreeStyleTab.readyToOpenChildTabCore(TreeStyleTab.getParentTab(gBrowser.selectedTab)||gBrowser.selectedTab); },readyToOpenChildTab:function(){ caisui.TreeStyleTab.readyToOpenChildTabCore(gBrowser.selectedTab,true); },stopToOpenChildTab:function(){ TreeStyleTabService.stopToOpenChildTab(gBrowser.selectedTab); },showTabbar:function(){ gBrowser.treeStyleTab.showTabbar(); },setMarkTab:function(){ markTab = gBrowser.selectedTab; },moveChildTab:function(){ var t=gBrowser.selectedTab; caisui.TreeStyleTab.performDrop(markTab,t , caisui.TreeStyleTab.getInsertBeforeTab(t)); },moveNextTab:function(){ var t=gBrowser.selectedTab; caisui.TreeStyleTab.performDrop(markTab,TreeStyleTabService.getParentTab(t) , caisui.TreeStyleTab.getInsertBeforeTab(t)); },performDrop:function(aTab,pTab,iTab){ if(!aTab) return; else if(pTab && TreeStyleTabService.getChildTabs(aTab,[]).indexOf(pTab)>=0){ liberator.echoerr("error:loop"); return; } gBrowser.treeStyleTab.performDrop({ action: (pTab ? TreeStyleTabService.kACTION_ATTACH:TreeStyleTabService.kACTION_PART)|TreeStyleTabService.kACTION_MOVE ,parent: pTab ,source: aTab ,insertBefore: iTab ,canDrop:true //,position: 0 //? //,target: null//? },aTab); },getInsertBeforeTab:function(aTab){ var ret=null; for(let t = aTab;t;t=TreeStyleTabService.getParentTab(t)){ if(ret=TreeStyleTabService.getNextSiblingTab(t)) break; } return ret; },moveUp:function(){ var t=gBrowser.selectedTab,p=TreeStyleTabService.getParentTab(t); if(!p) return; caisui.TreeStyleTab.performDrop(t,TreeStyleTabService.getParentTab(p),caisui.TreeStyleTab.getInsertBeforeTab(p)); },moveRoot:function(){ var t=gBrowser.selectedTab,r=TreeStyleTabService.getRootTab(t); caisui.TreeStyleTab.performDrop(t,null,caisui.TreeStyleTab.getInsertBeforeTab(r)); } }; let markTab=null; caisui = liberator.plugins.caisui; })();