diff options
-rw-r--r-- | autoIgnoreKey.js | 48 | ||||
-rw-r--r-- | copy.js | 168 | ||||
-rw-r--r-- | gmperator.js | 217 | ||||
-rw-r--r--[-rwxr-xr-x] | lookupDictionary.js | 0 | ||||
-rw-r--r-- | splitBrowser.js | 277 | ||||
-rw-r--r-- | xpathBlink.js | 59 |
6 files changed, 769 insertions, 0 deletions
diff --git a/autoIgnoreKey.js b/autoIgnoreKey.js new file mode 100644 index 0000000..07dd218 --- /dev/null +++ b/autoIgnoreKey.js @@ -0,0 +1,48 @@ +/** + * Auto switch vimperator key navigation + * For vimperator 0.5.3 + * @author teramako teramako@gmail.com + * @version 0.3 + */ + +(function(){ +/* + * String or RegExp + * e.g) + * * /^https?:\/\/mail\.google\.com\// + * * 'http://reader.livedoor.com/reader/' + */ +const ignorePageList = [ + /^https?:\/\/mail\.google\.com\//, + /^http:\/\/reader\.livedoor\.com\/(?:reader|public)\// +]; +document.getElementById('appcontent').addEventListener('DOMContentLoaded',function(event){ + if (event.target.documentURI != gBrowser.currentURI.spec) return; + if ( isMatch(event.target.documentURI) ){ + vimperator.addMode(null, vimperator.modes.ESCAPE_ALL_KEYS); + } else { + vimperator.setMode(vimperator.modes.NORMAL); + } + //vimperator.log('load page: ' + gBrowser.selectedBrowser.contentDocument.URL); +},false); +getBrowser().mTabBox.addEventListener('TabSelect',function(event){ + var uri = this.parentNode.currentURI.spec; + if ( isMatch(uri) ){ + vimperator.addMode(null, vimperator.modes.ESCAPE_ALL_KEYS); + } else { + vimperator.setMode(vimperator.modes.NORMAL); + } + //vimperator.log('select page: ' + gBrowser.selectedBrowser.contentDocument.URL); +},false); +function isMatch(uri){ + return ignorePageList.some(function(e,i,a){ + if (typeof e == 'string'){ + return uri.indexOf(e) != -1; + } else if (e instanceof RegExp){ + return e.test(uri); + } + }); +} +})(); + +// vim: set fdm=marker sw=4 ts=4 et: @@ -0,0 +1,168 @@ +/** + * vimperator plugin + * Add `copy' command + * For vimperator 0.5.3 + * @author teramako teramako@gmail.com + * @version 0.1 + * + * Usage: + * :copy {copyString} -> copy the argument replaced some certain string + * :copy! {expr} -> evaluate the argument and copy the result + * + * ex) + * :copy %TITLE% -> copied the title of the current page + * :copy title -> same as `:copy %TITLE%' by default + * :copy! vimperator.version -> copy the value of vimperator.version + * + * If non-argument, used `default' + * + * Change the value by `set' command. (only the current session) + * :set copy_{label}=.... + * or + * :set {label}=... + */ + +(function(){ +/* + * label: template name which is command argument + * copy: copy string + * the certian string is replace to ... + * %TITTLE% -> to the title of the current page + * %URL% -> to the URL of the current page + * %SEL% -> to the string of selection + * %HTMLSEL% -> to the html string of selection + */ +const templates = [ + { label: 'titleAndURL', value: '%TITLE%\n%URL%' }, + { label: 'title', value: '%TITLE%' }, + { label: 'anchor', value: '<a href="%URL%">%TITLE%</a>' }, + { label: 'selanchor', value: '<a href="%URL%" title="%TITLE%">%SEL%</a>' }, + { label: 'htmlblockquote', value: '<blockquote cite="%URL%" title="%TITLE%">%HTMLSEL%</blockquote>' } +]; +// used when argument is none +const defaultValue = templates[0].label; +vimperator.commands.add(new vimperator.Command( ['copy'], + function(arg, special){ + var copyString = ''; + var isError = false; + if (special && arg){ + try { + copyString = window.eval('with(vimperator){' + arg + '}'); + switch (typeof copyString){ + case 'object': + copyString = copyString === null ? 'null' : copyString.toSource(); + break; + case 'function': + copyString = copyString.toString(); + break; + case 'number': + case 'boolean': + copyString = '' + copyString; + break; + case 'undefined': + copyString = 'undefined'; + break; + } + } catch(e){ + isError = true; + copyString = e.toString(); + } + } else { + if (!arg){ arg = defaultValue; } + var str = getCopyTemplate(arg) || arg; + copyString = replaceVariable(str); + } + vimperator.copyToClipboard(copyString); + if (isError){ + vimperator.echoerr('CopiedErrorString: `' + copyString + "'"); + } else { + vimperator.echo('CopiedString: `' + vimperator.util.escapeHTML(copyString) + "'"); + } + },{ + usage: ['copy {copyString}','copy! {expr}'], + shortHelp: 'Copy to clipboard', + completer: function(filter){ + if ( vimperator.commands.parseCommand(vimperator.commandline.getCommand())[2] ){ + return vimperator.completion.javascript(filter); + } + var templates = []; + for (var option in vimperator.options){ + if ( option.name.indexOf('copy_') == 0 ){ + templates.push([option.names[1], option.value]); + } + } + if (!filter){ return templates; } + var candidates = []; + templates.forEach(function(template){ + if (template[0].indexOf(filter) == 0 || ('copy_'+template[0]).indexOf(filter) == 0){ + candidates.push(template); + } + }); + return candidates; + } + } +)); +function getCopyTemplate(label){ + for (var option in vimperator.options){ + if ( option.hasName('copy_'+label) || option.hasName(label) ){ + return option.value; + } + } + return null; +} +function replaceVariable(str){ + if (!str) return; + var win = new XPCNativeWrapper(window.content.window); + var sel = '',htmlsel = ''; + if (str.indexOf('%SEL%') >= 0 || str.indexOf('%HTMLSEL%') >= 0){ + sel = win.getSelection().getRangeAt(0); + } + if (str.indexOf('%HTMLSEL%') >= 0){ + var serializer = new XMLSerializer(); + htmlsel = serializer.serializeToString(sel.cloneContents()); + } + return str.replace(/%TITLE%/g,vimperator.buffer.title) + .replace(/%URL%/g,vimperator.buffer.URL) + .replace(/%SEL%/g,sel.toString()) + .replace(/%HTMLSEL%/g,htmlsel); +} + +templates.forEach(function(template){ + vimperator.options.add(new vimperator.Option( ['copy_'+template.label, template.label], 'string',{ + defaultValue: template.value, + shortHelp: 'Copy template: `' + vimperator.util.escapeHTML(template.value) + "'" + })); +}); +vimperator.completion.exTabCompletion = function (str) { + var [count, cmd, special, args] = vimperator.commands.parseCommand(str); + var completions = []; + var start = 0; + var matches = str.match(/^:*\d*(?=\w*$)/); + if (matches) { + completions = this.command(cmd); + start = matches[0].length; + } else { + var command = vimperator.commands.get(cmd); + if (command && command.completer) { + matches = str.match(/^:*\d*\w+!?\s+/); + start = matches ? matches[0].length : 0; + if (command.hasName("open") || command.hasName("tabopen") || command.hasName("winopen")) { + var skip = args.match(/^(.*,\s+)(.*)/); + if (skip) { + start += skip[1].length; + args = skip[2]; + } + } else if (command.hasName("echo") || command.hasName("echoerr") || + command.hasName("javascript") || command.hasName("copy")) { + var skip = args.match(/^.*?(?=\w*$)/); + if (skip) + start += skip[0].length; + } + completions = command.completer.call(this, args); + } + } + return [start, completions]; +}; +})(); + +// vim: set fdm=marker sw=4 ts=4 et: diff --git a/gmperator.js b/gmperator.js new file mode 100644 index 0000000..ba92925 --- /dev/null +++ b/gmperator.js @@ -0,0 +1,217 @@ +/** + * gmperator - vimperator plugin for Greasemonkey + * For vimperator 0.5.3 + * @author teramako teramako@gmail.com + * @version 0.1a + * + * Usage: + * + * :gmli[st] {filter} -> show user scripts matches {filter} + * :gmli[st]! -> show all user scripts + * :gmli[st] full -> same as :gmli[st]! + * + * :gmlo[ad] {name|filename} -> load the user script to the current page + * but, don't dispatch load event + * so maybe you should edit the scripts before load + * + * :gmset! -> toggle enable/disable greasemonkey + * :gmset! {filename} -> toogle enable/disable the script + * :gmset {filename} {options} + * {options}: + * n[ame]={value} -> change name to {value} + * i[nclude]={expr[,expr,...]} -> change includes to expr list ("," demiliter) + * e[xclude]={expr[,expr,...]} -> change excludes to expr list ("," demiliter) + * + * Caution: + * The change is permanent, not only the session. + * And cannot get back. + * + * ex) + * :gmset! {filename} n=fooScriptName i=http://*,https://* e=http://example.com/* + * toggle enable or disable, + * name to "fooScriptName", + * includes to "http://*" and "https://*", + * and excludes to "http://example.com/*" + */ +(function(){ +vimperator.commands.add(new vimperator.Command( + ['gmli[st]','lsgm'], + function(arg,special){ + var str = ''; + var scripts = getScripts(); + var reg; + if (special || arg == 'full'){ + reg = new RegExp('.*'); + } else if( arg ){ + reg = new RegExp(arg,'i'); + } + if (reg){ + for (var i=0; i<scripts.length; i++){ + if ( reg.test(scripts[i].name) || reg.test(scripts[i].filename) ) { + str += scriptToString(scripts[i]) + '\n\n'; + } + } + } else { + for (var i=0; i<scripts.length; i++){ + if (scripts[i].enabled){ + str += '<span style="font-weight:bold;">'+ scripts[i].name + '</span>' + } else { + str += scripts[i].name; + } + str += ' (' + scripts[i].filename + ')\n' + } + } + vimperator.echo(str); + function scriptToString(script){ + return [ + '<span class="hl-Title">' + script.name + '</span>::', + '<span style="font-weight:bold;">fileName</span>: ' + script.filename, + '<span style="font-weight:bold;">nameSpace</span>: ' + script.namespace, + '<span style="font-weight:bold;">description</span>: ' + script.description, + '<span style="font-weight:bold;">includes</span>:', + ' ' + script.includes.join('\n '), + '<span style="font-weight:bold;">excludes</span>:', + ' ' + script.excludes.join('\n '), + '<span style="font-weight:bold;">enabled</span>: ' + script.enabled + ].join('\n'); + } + },{ + usage: ['gmli[st] [full] | {filter}','lsgm [full] | {filter}'], + shortHelp: 'list Greasemonkey scripts' + } +)); +vimperator.commands.add(new vimperator.Command( + ['gmlo[ad]'], + function(arg){ + if (!arg) return; + var scripts = getScripts(); + var script; + for (var i=0; i<scripts.length; i++){ + if (scripts[i].filename == arg || scripts[i].name == arg){ + script = scripts[i]; + break; + } + } + if (!script) { + vimperator.echoerr('Usage: :gmlo[ad] {name|filename}'); + return; + } else { + vimperator.echo('load: ' +script.filename); + } + try { + var href = vimperator.buffer.URL; + var unsafewin = window.content.document.defaultView.wrappedJSObject; + GM_BrowserUI.gmSvc.wrappedJSObject.injectScripts([script],href,unsafewin,window); + } catch(e){ + vimperator.log(e); + } + /* + // do you have idea how to dispatch load event to only the script ? + window.setTimeout(function(){ + var loadEvent = document.createEvent('Event'); + loadEvent.initEvent('load',true,true, window.content.document,1); + window.content.document.dispatchEvent(loadEvent); + },100); + */ + },{ + usage: ['gmlo[ad] {name|filename}'], + shortHelp: 'load Greasemonkey script', + completer: function(filter){ + return scriptsCompleter(filter,true); + } + } +)); +vimperator.commands.add(new vimperator.Command( + ['gmset'], + function(arg, special){ + if (!arg && special) { // toggle enable/disable greasemonkey + GM_setEnabled(!GM_getEnabled()); + return; + } + var args = arg.split(/\s+/); + var filename = args.shift(); + var config = new Config(); + config.load(); + var script; + for (var i=0; i<config.scripts.length; i++){ + if (config.scripts[i].filename == filename){ + script = config.scripts[i]; + break; + } + } + if (!script) return; + if (special){ // toggle enable/disable the script if {filename} is exist + script.enabled = !script.enabled; + } + for (var i=0; i<args.length; i++){ + var [,key,value] = args[i].match(/(\w+)=(.*)$/); + switch(key){ + case 'n': + case 'name': + script.name = value; + break; + case 'i': + case 'include': + script.includes = value.split(','); + break; + case 'e': + case 'exclude': + script.excludes = value.split(','); + break; + } + } + config.save(); + },{ + usage: [ + 'gmset!', + 'gmset[!] {filename}', + 'gmset[!] {filename} n[ame]={name}', + 'gmset[!] {filename} i[nclude]={expr[,expr,...]}', + 'gmset[!] {filename} e[xeclude]={expr[,expr,...]}' + ], + shortHelp: 'change setting a greasemonkey script', + help: [ + 'toggle enable/disable with "!", if <code>{filename}</code> is exist, if not toggle greasemonkey', + '<dl><dt>n<br/>name</dt><dd>change the name</dd>', + '<dt>i<br/>include</dt><dd>change the inclue list ("," demiliter)</dd>', + '<dt>e<br/>exclude</dt><dd>change the exclude list ("," demiliter)</dd></dl>', + 'Caution: the change is permanent, not the only session.<br/>And cannot get back.' + ].join(''), + completer: function(filter){ + return scriptsCompleter(filter, false); + } + } +)); +function getScripts(){ + var config = new Config(); + config.load(); + return config.scripts; +} +function scriptsCompleter(filter,flag){ + var candidates = []; + var scripts = getScripts(); + var isAll = false; + if (!filter) isAll=true; + if (flag){ + for (var i=0; i<scripts.length; i++){ + if (isAll || scripts[i].name.toLowerCase().indexOf(filter) == 0 || + scripts[i].filename.indexOf(filter) == 0) + { + candidates.push([scripts[i].name, scripts[i].description]); + candidates.push([scripts[i].filename, scripts[i].description]); + } + } + } else { + for (var i=0; i<scripts.length; i++){ + if (isAll || scripts[i].filename.indexOf(filter) == 0) + { + candidates.push([scripts[i].filename, scripts[i].description]); + } + } + } + return candidates; +} + +})(); + +// vim: set fdm=marker sw=4 ts=4 et: diff --git a/lookupDictionary.js b/lookupDictionary.js index fd27d85..fd27d85 100755..100644 --- a/lookupDictionary.js +++ b/lookupDictionary.js diff --git a/splitBrowser.js b/splitBrowser.js new file mode 100644 index 0000000..e87e99a --- /dev/null +++ b/splitBrowser.js @@ -0,0 +1,277 @@ +/** + * Vimperator Plugin For "Split Browser" + * For vimperator 0.5.3 + * @author teramako + */ + +(function(){ + +vimperator.commands.add(new vimperator.Command(['sp[lit]'], + function(args){ + var position = null; + if (args) { + args = args.split(/ -/); + switch (args[args.length-1].toLowerCase()) { + case 'l': + case 'left': position = SplitBrowser.POSITION_LEFT; break; + case 'r': + case 'right': position = SplitBrowser.POSITION_RIGHT; break; + case 't': + case 'top': position = SplitBrowser.POSITION_TOP; break; + case 'bottom': + case 'b': position = SplitBrowser.POSITION_BOTTOM; break; + } + if (position) { + args.pop(); + } + var urls = args.join(' -'); + if (urls){ + urls = vimperator.util.stringToURLArray(urls); + var url = typeof urls[0] == 'string' ? urls[0] : urls[0][0]; + openSubBrowser(url, position); + return; + } + } + vimperator.echo('Split and load current URL.'); + openSubBrowser(vimperator.buffer.URL, position); + },{ + usage: ['sp[lit] [URL] [-POSITION]'], + shortHelp: 'split browser', + help: 'Split browser and load the <code class="argument">[URL]</code>.<br/>' + + 'If you don\'t specify the <code class="argument">[URL]</code> argument, browser loads the current URL.<br/>' + + '<br/>You need install <a href="https://addons.mozilla.org/en-US/firefox/addon/4287">Split Browser</a>.', + completer:function(filter){ return vimperator.completion.get_url_completions(filter); } + } +)); +vimperator.commands.add(new vimperator.Command(['on[ly]'], + function(){ + if (SplitBrowser.browsers.length > 0) { + SplitBrowser.removeAllSubBrowsers(); // 分割したブラウザをすべて閉じる + // 好みで↑↓選ぼう + // SplitBrowser.gatherSubBrowsers(); // すべての分割したブラウザをタブに集める + } else { + vimperator.echoerr('SubBrowser is none'); + } + },{ + usage: ['on[ly]'], + shortHelp: 'close split browsers', + help: 'Close all split browsers' + } +)); + +/** + * Close active browser + */ +vimperator.mappings.add(new vimperator.Map(vimperator.modes.NORMAL, ['sd'], //{{{ + function(){ + var b = SplitBrowser.activeBrowser; + if (b.mTabs.length > 1){ + b.removeTab(b.mCurrentTab); + } else { + if (b === gBrowser){ + vimperator.open('about:blank', vimperator.NEW_BACKGROUND_TAB); + gBrowser.removeTab(gBrowser.mCurrentTab); + } else { + SplitBrowser.activeBrowserCloseWindow(); + } + } + },{ + shortHelp: 'Close active browser' + } +)); //}}} +/** + * Switch browser focus + */ +vimperator.mappings.add(new vimperator.Map(vimperator.modes.NORMAL, ['<C-w><C-w>'], //{{{ + function(){ + var browsers = SplitBrowser.browsers; + if (SplitBrowser.activeBrowser === gBrowser) { + SplitBrowser.getSubBrowserById(browsers[0].id).browser.contentWindow.focus(); + } else { + var id = SplitBrowser.activeSubBrowser.id; + for (var i=0; i<browsers.length; i++){ + if (browsers[i].id == id) { + if (browsers[i+1]){ + SplitBrowser.getSubBrowserById(browsers[i+1].id).browser.contentWindow.focus(); + } else { + gBrowser.contentWindow.focus(); + } + return true; + } + } + } + },{ + shortHelp: 'Switch focus', + help: 'Switch focus to splitted browser' + } +)); //}}} + +/** + * Overwrite save hint `s' to `S' + */ +vimperator.mappings.add(new vimperator.Map(vimperator.modes.HINTS, ['S'], //{{{ + function(){ vimperator.hints.saveHints(true); }, + { + cancelMode: true, + alwaysActive: false + } +)); //}}} +/** + * ExtendedHint mode key mapping `s' + * This key mapping is prefix for open the urls to split browser + */ +vimperator.mappings.add(new vimperator.Map(vimperator.modes.HINTS, ['s'], //{{{ + function(){ + vimperator.input.buffer += 's'; + vimperator.echo("-- HINTS (extended) -- Split: `t': TOP, `b': BOTTOM, `l':LEFT, `r':RIGHT"); + },{ + cancelMode:false, + alwaysActive:true + } +)); // }}} +/** + * ExtendedHint mode key mapping `t' + * Split to TOP + */ +vimperator.mappings.add(new vimperator.Map(vimperator.modes.HINTS, ['t'], //{{{ + function(){ + var input = vimperator.input.buffer; + if (input.charAt(input.length-1) == 's'){ + openSubBrowserExtendedMode(SplitBrowser.POSITION_TOP); + } else { + vimperator.hints.openHints(true, false); + } + vimperator.hints.disableHahMode(null,true); + },{ + cancelMode:true, + alwaysActive:false + } +)); //}}} +/** + * ExtendedHint mode key mapping `b' + * Split to BOTTOM + */ +vimperator.mappings.add(new vimperator.Map(vimperator.modes.HINTS, ['b'], //{{{ + function(){ + var input = vimperator.input.buffer; + if (input.charAt(input.length-1) == 's'){ + openSubBrowserExtendedMode(SplitBrowser.POSITION_BOTTOM); + } + vimperator.hints.disableHahMode(null,true); + },{ + cancelMode:true, + alwaysActive:false + } +)); //}}} +/** + * ExtendedHint mode key mapping `l' + * Split to LEFT + */ +vimperator.mappings.add(new vimperator.Map(vimperator.modes.HINTS, ['l'], //{{{ + function(){ + var input = vimperator.input.buffer; + if (input.charAt(input.length-1) == 's'){ + openSubBrowserExtendedMode(SplitBrowser.POSITION_LEFT); + } + vimperator.hints.disableHahMode(null,true); + },{ + cancelMode:true, + alwaysActive:false + } +)); //}}} +/** + * ExtendedHint mode key mapping `r' + * Split to RIGHT + */ +vimperator.mappings.add(new vimperator.Map(vimperator.modes.HINTS, ['r'], //{{{ + function(){ + var input = vimperator.input.buffer; + if (input.charAt(input.length-1) == 's'){ + openSubBrowserExtendedMode(SplitBrowser.POSITION_RIGHT); + } + vimperator.hints.disableHahMode(null,true); + },{ + cancelMode:true, + alwaysActive:false + } +)); //}}} +/** + * openSubBrowser at ExtendedHint mode + * @param {Number} aPosition split direction + */ +function openSubBrowserExtendedMode(aPosition){ //{{{ + var elms = vimperator.hints.hintedElements(); + var urls = []; + for (var i=0; i<elms.length; i++){ + var url = elms[i].refElem.href; + if (typeof(url) == 'undefined' || !url.length){ + continue; + } + urls.push(url); + } + if (urls.length == 0) { return; } + var subBrowser = openSubBrowser(urls[0], aPosition); + if (urls.length > 1){ + for (var i=1, l=urls.length; i < l; subBrowser.browser.addTab(urls[i++],null,null,null)) + ; + } +} //}}} +/** + * create new subBrowser and load url + * @param {String} url + * @param {Number} aPosition split direction + */ +function openSubBrowser(url, aPosition){ // {{{ + var subBrowser = SplitBrowser.addSubBrowser(url, null, aPosition || SplitBrowser.POSITION_TOP); + subBrowser.addEventListener('load',function(){ + subBrowser.removeEventListener('load',arguments.callee,true); + subBrowser.browser.contentWindow.focus(); + },true); + return subBrowser; +} //}}} + +/** + * Overwrite vimperator.open for SplitBrowser + * @see vimperator.js::vimperaotr.open + */ +vimperator.open = function(urls, where, callback){ //{{{ + if (typeof urls == 'string') { urls = vimperator.util.stringToURLArray(urls); } + if (urls.length == 0) { return false; } + if (!where) { where = vimperator.CURRENT_TAB; } + + var url = typeof urls[0] == 'string' ? urls[0] : urls[0][0]; + var postdata = typeof urls[0] == 'string' ? null : urls[0][1]; + var whichwindow = window; + var activeBrowser = SplitBrowser.activeBrowser; + + switch (where) { + case vimperator.CURRENT_TAB: + activeBrowser.loadURI(url, null, postdata); + break; + case vimperator.NEW_TAB: + var firsttab = activeBrowser.addTab(url, null, null, postdata); + activeBrowser.selectedTab = firsttab; + break; + case vimperator.NEW_BACKGROUND_TAB: + activeBrowser.addTab(url, null, null, postdata); + break; + case vimperator.NEW_WINDOW: + window.open(); + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + whichwindow = vm.getMostRecentWindow('navigator:browser'); + whichwindow.loadURI(url, null, postdata); + break; + default: + vimperator.echoerr("Exxx: Invalid 'where' directive in vimperator.open(...)"); + return false; + } + for (var i=1, l=urls.length; i < l; i++){ + url = typeof urls[i] == 'string' ? urls[i] : urls[i][0]; + postdata = typeof urls[i] == 'string' ? null : urls[i][1]; + whichwindow.SplitBrowser.activeBrowser.addTab(url, null, null, postdata); + } +}; //}}} +})(); + +// vim: set fdm=marker sw=4 ts=4 et: diff --git a/xpathBlink.js b/xpathBlink.js new file mode 100644 index 0000000..a55c997 --- /dev/null +++ b/xpathBlink.js @@ -0,0 +1,59 @@ +/** + * For vimperator 0.5.3 + * @author teramako teramako@gmail.com + */ +(function(){ +const Cc = Components.classes; +const Ci = Components.interfaces; +var flasher = null; +function getFlasher(){ + if (!flasher){ + flasher = Cc['@mozilla.org/inspector/flasher;1'].createInstance(Ci.inIFlasher); + flasher.color = '#FF0000'; + flasher.thickness = 2; + } + return flasher; +} +/** + * @param {Node} aNode + */ +function blink(aNode){ + if (aNode.nodeType == 3) aNode = aNode.parentNode; + var toggle = true; + var flasher = getFlasher(); + function setOutline(){ + if(toggle){ + flasher.drawElementOutline(aNode); + }else { + flasher.repaintElement(aNode); + } + toggle = !toggle; + } + for (var i=1; i<7; ++i){ + setTimeout(setOutline, i * 100); + } +} +vimperator.commands.add(new vimperator.Command(['xpathb[link]','xb'], + function(expression){ + var result + try { + result = vimperator.buffer.evaluateXPath(expression); + } catch(e) { + vimperator.echoerr('XPath blink: ' + e); + } + if (!result.snapshotLength){ + vimperator.echo('XPath blink: none'); + return; + } + for (var i=0; i<result.snapshotLength; i++){ + blink(result.snapshotItem(i)); + } + },{ + usage: ['xpathb[link] [EXPRESSION]','xb [EXPERSSION]'], + shortHelp: 'XPath blink nodes', + help: 'Search nodes with XPath [EXPRESSION] and blink the nodes' + } +)); +})(); + +// vim: set fdm=marker sw=4 ts=4 et: |